├── .gitignore ├── .gitmodules ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── base ├── Cargo.toml └── src │ ├── lib.rs │ └── types.rs ├── build.rs ├── flake.lock ├── flake.nix ├── src ├── config.rs ├── error.rs ├── lib.rs ├── main.rs ├── matrix.rs └── web │ ├── category_list.rs │ ├── extract.rs │ ├── mod.rs │ ├── post.rs │ ├── post_list.rs │ └── user_error.rs └── ui ├── Cargo.toml ├── Trunk.toml ├── index.html ├── src ├── category_list.rs ├── lib.rs ├── main.rs ├── post.rs └── post_list.rs └── styles ├── base.scss ├── contrast.scss ├── dark.scss ├── events.scss ├── highlight-dark.scss ├── highlight.scss ├── icons.scss ├── nav.scss └── variables.scss /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | ui/dist 3 | shell.nix 4 | config.yaml 5 | appservice-registration.yaml 6 | result -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ui/css/bootstrap"] 2 | path = ui/styles/bootstrap 3 | url = https://github.com/twbs/bootstrap 4 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aead" 7 | version = "0.4.3" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" 10 | dependencies = [ 11 | "generic-array", 12 | "rand_core 0.6.4", 13 | ] 14 | 15 | [[package]] 16 | name = "aead" 17 | version = "0.5.1" 18 | source = "registry+https://github.com/rust-lang/crates.io-index" 19 | checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8" 20 | dependencies = [ 21 | "crypto-common", 22 | "generic-array", 23 | ] 24 | 25 | [[package]] 26 | name = "aes" 27 | version = "0.8.2" 28 | source = "registry+https://github.com/rust-lang/crates.io-index" 29 | checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" 30 | dependencies = [ 31 | "cfg-if", 32 | "cipher 0.4.3", 33 | "cpufeatures", 34 | ] 35 | 36 | [[package]] 37 | name = "aes-gcm" 38 | version = "0.10.1" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | checksum = "82e1366e0c69c9f927b1fa5ce2c7bf9eafc8f9268c0b9800729e8b267612447c" 41 | dependencies = [ 42 | "aead 0.5.1", 43 | "aes", 44 | "cipher 0.4.3", 45 | "ctr", 46 | "ghash", 47 | "subtle", 48 | ] 49 | 50 | [[package]] 51 | name = "ahash" 52 | version = "0.7.6" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" 55 | dependencies = [ 56 | "getrandom 0.2.8", 57 | "once_cell", 58 | "version_check", 59 | ] 60 | 61 | [[package]] 62 | name = "aho-corasick" 63 | version = "0.7.20" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" 66 | dependencies = [ 67 | "memchr", 68 | ] 69 | 70 | [[package]] 71 | name = "anymap2" 72 | version = "0.13.0" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" 75 | 76 | [[package]] 77 | name = "arrayref" 78 | version = "0.3.6" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" 81 | 82 | [[package]] 83 | name = "arrayvec" 84 | version = "0.7.2" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" 87 | 88 | [[package]] 89 | name = "assign" 90 | version = "1.1.1" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "5f093eed78becd229346bf859eec0aa4dd7ddde0757287b2b4107a1f09c80002" 93 | 94 | [[package]] 95 | name = "async-lock" 96 | version = "2.6.0" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" 99 | dependencies = [ 100 | "event-listener", 101 | "futures-lite", 102 | ] 103 | 104 | [[package]] 105 | name = "async-once-cell" 106 | version = "0.3.1" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "72faff1fdc615a0199d7bf71e6f389af54d46a66e9beb5d76c39e48eda93ecce" 109 | 110 | [[package]] 111 | name = "async-stream" 112 | version = "0.3.3" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" 115 | dependencies = [ 116 | "async-stream-impl", 117 | "futures-core", 118 | ] 119 | 120 | [[package]] 121 | name = "async-stream-impl" 122 | version = "0.3.3" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" 125 | dependencies = [ 126 | "proc-macro2", 127 | "quote", 128 | "syn", 129 | ] 130 | 131 | [[package]] 132 | name = "async-trait" 133 | version = "0.1.59" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364" 136 | dependencies = [ 137 | "proc-macro2", 138 | "quote", 139 | "syn", 140 | ] 141 | 142 | [[package]] 143 | name = "autocfg" 144 | version = "1.1.0" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 147 | 148 | [[package]] 149 | name = "axum" 150 | version = "0.6.1" 151 | source = "registry+https://github.com/rust-lang/crates.io-index" 152 | checksum = "08b108ad2665fa3f6e6a517c3d80ec3e77d224c47d605167aefaa5d7ef97fa48" 153 | dependencies = [ 154 | "async-trait", 155 | "axum-core", 156 | "axum-macros", 157 | "bitflags", 158 | "bytes", 159 | "futures-util", 160 | "headers", 161 | "http", 162 | "http-body", 163 | "hyper", 164 | "itoa", 165 | "matchit", 166 | "memchr", 167 | "mime", 168 | "percent-encoding", 169 | "pin-project-lite", 170 | "rustversion", 171 | "serde", 172 | "serde_json", 173 | "serde_path_to_error", 174 | "serde_urlencoded", 175 | "sync_wrapper", 176 | "tokio", 177 | "tower", 178 | "tower-http", 179 | "tower-layer", 180 | "tower-service", 181 | ] 182 | 183 | [[package]] 184 | name = "axum-core" 185 | version = "0.3.0" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "79b8558f5a0581152dc94dcd289132a1d377494bdeafcd41869b3258e3e2ad92" 188 | dependencies = [ 189 | "async-trait", 190 | "bytes", 191 | "futures-util", 192 | "http", 193 | "http-body", 194 | "mime", 195 | "rustversion", 196 | "tower-layer", 197 | "tower-service", 198 | ] 199 | 200 | [[package]] 201 | name = "axum-extra" 202 | version = "0.4.2" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "f9a320103719de37b7b4da4c8eb629d4573f6bcfd3dfe80d3208806895ccf81d" 205 | dependencies = [ 206 | "axum", 207 | "bytes", 208 | "cookie", 209 | "futures-util", 210 | "http", 211 | "mime", 212 | "pin-project-lite", 213 | "tokio", 214 | "tower", 215 | "tower-http", 216 | "tower-layer", 217 | "tower-service", 218 | ] 219 | 220 | [[package]] 221 | name = "axum-macros" 222 | version = "0.3.0" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "e4df0fc33ada14a338b799002f7e8657711422b25d4e16afb032708d6b185621" 225 | dependencies = [ 226 | "heck", 227 | "proc-macro2", 228 | "quote", 229 | "syn", 230 | ] 231 | 232 | [[package]] 233 | name = "backoff" 234 | version = "0.4.0" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" 237 | dependencies = [ 238 | "futures-core", 239 | "getrandom 0.2.8", 240 | "instant", 241 | "pin-project-lite", 242 | "rand 0.8.5", 243 | "tokio", 244 | ] 245 | 246 | [[package]] 247 | name = "base64" 248 | version = "0.13.1" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" 251 | 252 | [[package]] 253 | name = "base64ct" 254 | version = "1.5.3" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" 257 | 258 | [[package]] 259 | name = "bitflags" 260 | version = "1.3.2" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 263 | 264 | [[package]] 265 | name = "blake3" 266 | version = "1.3.3" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" 269 | dependencies = [ 270 | "arrayref", 271 | "arrayvec", 272 | "cc", 273 | "cfg-if", 274 | "constant_time_eq", 275 | "digest", 276 | ] 277 | 278 | [[package]] 279 | name = "block-buffer" 280 | version = "0.10.3" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" 283 | dependencies = [ 284 | "generic-array", 285 | ] 286 | 287 | [[package]] 288 | name = "build-helper" 289 | version = "0.1.1" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "bdce191bf3fa4995ce948c8c83b4640a1745457a149e73c6db75b4ffe36aad5f" 292 | dependencies = [ 293 | "semver 0.6.0", 294 | ] 295 | 296 | [[package]] 297 | name = "bumpalo" 298 | version = "3.11.1" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" 301 | 302 | [[package]] 303 | name = "byteorder" 304 | version = "1.4.3" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 307 | 308 | [[package]] 309 | name = "bytes" 310 | version = "1.3.0" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" 313 | 314 | [[package]] 315 | name = "cc" 316 | version = "1.0.77" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" 319 | 320 | [[package]] 321 | name = "cfg-if" 322 | version = "1.0.0" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 325 | 326 | [[package]] 327 | name = "chacha20" 328 | version = "0.8.2" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" 331 | dependencies = [ 332 | "cfg-if", 333 | "cipher 0.3.0", 334 | "cpufeatures", 335 | "zeroize", 336 | ] 337 | 338 | [[package]] 339 | name = "chacha20poly1305" 340 | version = "0.9.1" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5" 343 | dependencies = [ 344 | "aead 0.4.3", 345 | "chacha20", 346 | "cipher 0.3.0", 347 | "poly1305", 348 | "zeroize", 349 | ] 350 | 351 | [[package]] 352 | name = "cipher" 353 | version = "0.3.0" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" 356 | dependencies = [ 357 | "generic-array", 358 | ] 359 | 360 | [[package]] 361 | name = "cipher" 362 | version = "0.4.3" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" 365 | dependencies = [ 366 | "crypto-common", 367 | "inout", 368 | ] 369 | 370 | [[package]] 371 | name = "clap" 372 | version = "4.0.29" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d" 375 | dependencies = [ 376 | "bitflags", 377 | "clap_derive", 378 | "clap_lex", 379 | "is-terminal", 380 | "once_cell", 381 | "strsim", 382 | "termcolor", 383 | ] 384 | 385 | [[package]] 386 | name = "clap_derive" 387 | version = "4.0.21" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" 390 | dependencies = [ 391 | "heck", 392 | "proc-macro-error", 393 | "proc-macro2", 394 | "quote", 395 | "syn", 396 | ] 397 | 398 | [[package]] 399 | name = "clap_lex" 400 | version = "0.3.0" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" 403 | dependencies = [ 404 | "os_str_bytes", 405 | ] 406 | 407 | [[package]] 408 | name = "console_error_panic_hook" 409 | version = "0.1.7" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" 412 | dependencies = [ 413 | "cfg-if", 414 | "wasm-bindgen", 415 | ] 416 | 417 | [[package]] 418 | name = "constant_time_eq" 419 | version = "0.2.4" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279" 422 | 423 | [[package]] 424 | name = "convert_case" 425 | version = "0.4.0" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" 428 | 429 | [[package]] 430 | name = "cookie" 431 | version = "0.16.1" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "344adc371239ef32293cb1c4fe519592fcf21206c79c02854320afcdf3ab4917" 434 | dependencies = [ 435 | "aes-gcm", 436 | "base64", 437 | "percent-encoding", 438 | "rand 0.8.5", 439 | "subtle", 440 | "time", 441 | "version_check", 442 | ] 443 | 444 | [[package]] 445 | name = "cpufeatures" 446 | version = "0.2.5" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" 449 | dependencies = [ 450 | "libc", 451 | ] 452 | 453 | [[package]] 454 | name = "crc32fast" 455 | version = "1.3.2" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" 458 | dependencies = [ 459 | "cfg-if", 460 | ] 461 | 462 | [[package]] 463 | name = "crossbeam-epoch" 464 | version = "0.9.13" 465 | source = "registry+https://github.com/rust-lang/crates.io-index" 466 | checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" 467 | dependencies = [ 468 | "autocfg", 469 | "cfg-if", 470 | "crossbeam-utils", 471 | "memoffset", 472 | "scopeguard", 473 | ] 474 | 475 | [[package]] 476 | name = "crossbeam-utils" 477 | version = "0.8.14" 478 | source = "registry+https://github.com/rust-lang/crates.io-index" 479 | checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" 480 | dependencies = [ 481 | "cfg-if", 482 | ] 483 | 484 | [[package]] 485 | name = "crypto-common" 486 | version = "0.1.6" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 489 | dependencies = [ 490 | "generic-array", 491 | "rand_core 0.6.4", 492 | "typenum", 493 | ] 494 | 495 | [[package]] 496 | name = "ctr" 497 | version = "0.9.2" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" 500 | dependencies = [ 501 | "cipher 0.4.3", 502 | ] 503 | 504 | [[package]] 505 | name = "darling" 506 | version = "0.14.2" 507 | source = "registry+https://github.com/rust-lang/crates.io-index" 508 | checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa" 509 | dependencies = [ 510 | "darling_core", 511 | "darling_macro", 512 | ] 513 | 514 | [[package]] 515 | name = "darling_core" 516 | version = "0.14.2" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" 519 | dependencies = [ 520 | "fnv", 521 | "ident_case", 522 | "proc-macro2", 523 | "quote", 524 | "strsim", 525 | "syn", 526 | ] 527 | 528 | [[package]] 529 | name = "darling_macro" 530 | version = "0.14.2" 531 | source = "registry+https://github.com/rust-lang/crates.io-index" 532 | checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" 533 | dependencies = [ 534 | "darling_core", 535 | "quote", 536 | "syn", 537 | ] 538 | 539 | [[package]] 540 | name = "dashmap" 541 | version = "5.4.0" 542 | source = "registry+https://github.com/rust-lang/crates.io-index" 543 | checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" 544 | dependencies = [ 545 | "cfg-if", 546 | "hashbrown", 547 | "lock_api", 548 | "once_cell", 549 | "parking_lot_core 0.9.5", 550 | ] 551 | 552 | [[package]] 553 | name = "derive_builder" 554 | version = "0.11.2" 555 | source = "registry+https://github.com/rust-lang/crates.io-index" 556 | checksum = "d07adf7be193b71cc36b193d0f5fe60b918a3a9db4dad0449f57bcfd519704a3" 557 | dependencies = [ 558 | "derive_builder_macro", 559 | ] 560 | 561 | [[package]] 562 | name = "derive_builder_core" 563 | version = "0.11.2" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4" 566 | dependencies = [ 567 | "darling", 568 | "proc-macro2", 569 | "quote", 570 | "syn", 571 | ] 572 | 573 | [[package]] 574 | name = "derive_builder_macro" 575 | version = "0.11.2" 576 | source = "registry+https://github.com/rust-lang/crates.io-index" 577 | checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68" 578 | dependencies = [ 579 | "derive_builder_core", 580 | "syn", 581 | ] 582 | 583 | [[package]] 584 | name = "derive_more" 585 | version = "0.99.17" 586 | source = "registry+https://github.com/rust-lang/crates.io-index" 587 | checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" 588 | dependencies = [ 589 | "convert_case", 590 | "proc-macro2", 591 | "quote", 592 | "rustc_version", 593 | "syn", 594 | ] 595 | 596 | [[package]] 597 | name = "digest" 598 | version = "0.10.6" 599 | source = "registry+https://github.com/rust-lang/crates.io-index" 600 | checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" 601 | dependencies = [ 602 | "block-buffer", 603 | "crypto-common", 604 | "subtle", 605 | ] 606 | 607 | [[package]] 608 | name = "discard" 609 | version = "1.0.4" 610 | source = "registry+https://github.com/rust-lang/crates.io-index" 611 | checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" 612 | 613 | [[package]] 614 | name = "displaydoc" 615 | version = "0.2.3" 616 | source = "registry+https://github.com/rust-lang/crates.io-index" 617 | checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" 618 | dependencies = [ 619 | "proc-macro2", 620 | "quote", 621 | "syn", 622 | ] 623 | 624 | [[package]] 625 | name = "east" 626 | version = "0.3.0-dev" 627 | source = "git+https://github.com/corepaper/east#c1c55efeb6cbda4534e20fdf7241174e2edac522" 628 | dependencies = [ 629 | "east-macro", 630 | "serde", 631 | "serde_json", 632 | "sycamore", 633 | "wasm-bindgen", 634 | "web-sys", 635 | ] 636 | 637 | [[package]] 638 | name = "east-build" 639 | version = "0.1.0" 640 | source = "git+https://github.com/corepaper/east#c1c55efeb6cbda4534e20fdf7241174e2edac522" 641 | dependencies = [ 642 | "axum", 643 | "build-helper", 644 | "east", 645 | "include_dir", 646 | "mime", 647 | ] 648 | 649 | [[package]] 650 | name = "east-build-helper" 651 | version = "0.1.0" 652 | source = "git+https://github.com/corepaper/east#c1c55efeb6cbda4534e20fdf7241174e2edac522" 653 | dependencies = [ 654 | "build-helper", 655 | ] 656 | 657 | [[package]] 658 | name = "east-macro" 659 | version = "0.3.0-dev" 660 | source = "git+https://github.com/corepaper/east#c1c55efeb6cbda4534e20fdf7241174e2edac522" 661 | dependencies = [ 662 | "proc-macro-crate", 663 | "proc-macro2", 664 | "quote", 665 | "syn", 666 | ] 667 | 668 | [[package]] 669 | name = "encoding_rs" 670 | version = "0.8.31" 671 | source = "registry+https://github.com/rust-lang/crates.io-index" 672 | checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" 673 | dependencies = [ 674 | "cfg-if", 675 | ] 676 | 677 | [[package]] 678 | name = "errno" 679 | version = "0.2.8" 680 | source = "registry+https://github.com/rust-lang/crates.io-index" 681 | checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" 682 | dependencies = [ 683 | "errno-dragonfly", 684 | "libc", 685 | "winapi", 686 | ] 687 | 688 | [[package]] 689 | name = "errno-dragonfly" 690 | version = "0.1.2" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 693 | dependencies = [ 694 | "cc", 695 | "libc", 696 | ] 697 | 698 | [[package]] 699 | name = "event-listener" 700 | version = "2.5.3" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" 703 | 704 | [[package]] 705 | name = "fastrand" 706 | version = "1.8.0" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" 709 | dependencies = [ 710 | "instant", 711 | ] 712 | 713 | [[package]] 714 | name = "fnv" 715 | version = "1.0.7" 716 | source = "registry+https://github.com/rust-lang/crates.io-index" 717 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 718 | 719 | [[package]] 720 | name = "form_urlencoded" 721 | version = "1.1.0" 722 | source = "registry+https://github.com/rust-lang/crates.io-index" 723 | checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" 724 | dependencies = [ 725 | "percent-encoding", 726 | ] 727 | 728 | [[package]] 729 | name = "fs2" 730 | version = "0.4.3" 731 | source = "registry+https://github.com/rust-lang/crates.io-index" 732 | checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" 733 | dependencies = [ 734 | "libc", 735 | "winapi", 736 | ] 737 | 738 | [[package]] 739 | name = "fs_extra" 740 | version = "1.2.0" 741 | source = "registry+https://github.com/rust-lang/crates.io-index" 742 | checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" 743 | 744 | [[package]] 745 | name = "futf" 746 | version = "0.1.5" 747 | source = "registry+https://github.com/rust-lang/crates.io-index" 748 | checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" 749 | dependencies = [ 750 | "mac", 751 | "new_debug_unreachable", 752 | ] 753 | 754 | [[package]] 755 | name = "futures" 756 | version = "0.3.25" 757 | source = "registry+https://github.com/rust-lang/crates.io-index" 758 | checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" 759 | dependencies = [ 760 | "futures-channel", 761 | "futures-core", 762 | "futures-executor", 763 | "futures-io", 764 | "futures-sink", 765 | "futures-task", 766 | "futures-util", 767 | ] 768 | 769 | [[package]] 770 | name = "futures-channel" 771 | version = "0.3.25" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" 774 | dependencies = [ 775 | "futures-core", 776 | "futures-sink", 777 | ] 778 | 779 | [[package]] 780 | name = "futures-core" 781 | version = "0.3.25" 782 | source = "registry+https://github.com/rust-lang/crates.io-index" 783 | checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" 784 | 785 | [[package]] 786 | name = "futures-executor" 787 | version = "0.3.25" 788 | source = "registry+https://github.com/rust-lang/crates.io-index" 789 | checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" 790 | dependencies = [ 791 | "futures-core", 792 | "futures-task", 793 | "futures-util", 794 | ] 795 | 796 | [[package]] 797 | name = "futures-io" 798 | version = "0.3.25" 799 | source = "registry+https://github.com/rust-lang/crates.io-index" 800 | checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" 801 | 802 | [[package]] 803 | name = "futures-lite" 804 | version = "1.12.0" 805 | source = "registry+https://github.com/rust-lang/crates.io-index" 806 | checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" 807 | dependencies = [ 808 | "fastrand", 809 | "futures-core", 810 | "futures-io", 811 | "memchr", 812 | "parking", 813 | "pin-project-lite", 814 | "waker-fn", 815 | ] 816 | 817 | [[package]] 818 | name = "futures-macro" 819 | version = "0.3.25" 820 | source = "registry+https://github.com/rust-lang/crates.io-index" 821 | checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" 822 | dependencies = [ 823 | "proc-macro2", 824 | "quote", 825 | "syn", 826 | ] 827 | 828 | [[package]] 829 | name = "futures-signals" 830 | version = "0.3.31" 831 | source = "registry+https://github.com/rust-lang/crates.io-index" 832 | checksum = "a3acc659ba666cff13fdf65242d16428f2f11935b688f82e4024ad39667a5132" 833 | dependencies = [ 834 | "discard", 835 | "futures-channel", 836 | "futures-core", 837 | "futures-util", 838 | "pin-project", 839 | ] 840 | 841 | [[package]] 842 | name = "futures-sink" 843 | version = "0.3.25" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" 846 | 847 | [[package]] 848 | name = "futures-task" 849 | version = "0.3.25" 850 | source = "registry+https://github.com/rust-lang/crates.io-index" 851 | checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" 852 | 853 | [[package]] 854 | name = "futures-util" 855 | version = "0.3.25" 856 | source = "registry+https://github.com/rust-lang/crates.io-index" 857 | checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" 858 | dependencies = [ 859 | "futures-channel", 860 | "futures-core", 861 | "futures-io", 862 | "futures-macro", 863 | "futures-sink", 864 | "futures-task", 865 | "memchr", 866 | "pin-project-lite", 867 | "pin-utils", 868 | "slab", 869 | ] 870 | 871 | [[package]] 872 | name = "fxhash" 873 | version = "0.2.1" 874 | source = "registry+https://github.com/rust-lang/crates.io-index" 875 | checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" 876 | dependencies = [ 877 | "byteorder", 878 | ] 879 | 880 | [[package]] 881 | name = "generic-array" 882 | version = "0.14.6" 883 | source = "registry+https://github.com/rust-lang/crates.io-index" 884 | checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" 885 | dependencies = [ 886 | "typenum", 887 | "version_check", 888 | ] 889 | 890 | [[package]] 891 | name = "getopts" 892 | version = "0.2.21" 893 | source = "registry+https://github.com/rust-lang/crates.io-index" 894 | checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" 895 | dependencies = [ 896 | "unicode-width", 897 | ] 898 | 899 | [[package]] 900 | name = "getrandom" 901 | version = "0.1.16" 902 | source = "registry+https://github.com/rust-lang/crates.io-index" 903 | checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" 904 | dependencies = [ 905 | "cfg-if", 906 | "libc", 907 | "wasi 0.9.0+wasi-snapshot-preview1", 908 | ] 909 | 910 | [[package]] 911 | name = "getrandom" 912 | version = "0.2.8" 913 | source = "registry+https://github.com/rust-lang/crates.io-index" 914 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" 915 | dependencies = [ 916 | "cfg-if", 917 | "libc", 918 | "wasi 0.11.0+wasi-snapshot-preview1", 919 | ] 920 | 921 | [[package]] 922 | name = "ghash" 923 | version = "0.5.0" 924 | source = "registry+https://github.com/rust-lang/crates.io-index" 925 | checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" 926 | dependencies = [ 927 | "opaque-debug", 928 | "polyval", 929 | ] 930 | 931 | [[package]] 932 | name = "h2" 933 | version = "0.3.15" 934 | source = "registry+https://github.com/rust-lang/crates.io-index" 935 | checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" 936 | dependencies = [ 937 | "bytes", 938 | "fnv", 939 | "futures-core", 940 | "futures-sink", 941 | "futures-util", 942 | "http", 943 | "indexmap", 944 | "slab", 945 | "tokio", 946 | "tokio-util", 947 | "tracing", 948 | ] 949 | 950 | [[package]] 951 | name = "hashbrown" 952 | version = "0.12.3" 953 | source = "registry+https://github.com/rust-lang/crates.io-index" 954 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 955 | dependencies = [ 956 | "ahash", 957 | ] 958 | 959 | [[package]] 960 | name = "headers" 961 | version = "0.3.8" 962 | source = "registry+https://github.com/rust-lang/crates.io-index" 963 | checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" 964 | dependencies = [ 965 | "base64", 966 | "bitflags", 967 | "bytes", 968 | "headers-core", 969 | "http", 970 | "httpdate", 971 | "mime", 972 | "sha1", 973 | ] 974 | 975 | [[package]] 976 | name = "headers-core" 977 | version = "0.2.0" 978 | source = "registry+https://github.com/rust-lang/crates.io-index" 979 | checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" 980 | dependencies = [ 981 | "http", 982 | ] 983 | 984 | [[package]] 985 | name = "heck" 986 | version = "0.4.0" 987 | source = "registry+https://github.com/rust-lang/crates.io-index" 988 | checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" 989 | 990 | [[package]] 991 | name = "hermit-abi" 992 | version = "0.1.19" 993 | source = "registry+https://github.com/rust-lang/crates.io-index" 994 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 995 | dependencies = [ 996 | "libc", 997 | ] 998 | 999 | [[package]] 1000 | name = "hermit-abi" 1001 | version = "0.2.6" 1002 | source = "registry+https://github.com/rust-lang/crates.io-index" 1003 | checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" 1004 | dependencies = [ 1005 | "libc", 1006 | ] 1007 | 1008 | [[package]] 1009 | name = "hmac" 1010 | version = "0.12.1" 1011 | source = "registry+https://github.com/rust-lang/crates.io-index" 1012 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 1013 | dependencies = [ 1014 | "digest", 1015 | ] 1016 | 1017 | [[package]] 1018 | name = "html-escape" 1019 | version = "0.2.12" 1020 | source = "registry+https://github.com/rust-lang/crates.io-index" 1021 | checksum = "15315cfa9503e9aa85a477138eff76a1b203a430703548052c330b69d8d8c205" 1022 | dependencies = [ 1023 | "utf8-width", 1024 | ] 1025 | 1026 | [[package]] 1027 | name = "html5ever" 1028 | version = "0.25.2" 1029 | source = "registry+https://github.com/rust-lang/crates.io-index" 1030 | checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148" 1031 | dependencies = [ 1032 | "log", 1033 | "mac", 1034 | "markup5ever", 1035 | "proc-macro2", 1036 | "quote", 1037 | "syn", 1038 | ] 1039 | 1040 | [[package]] 1041 | name = "http" 1042 | version = "0.2.8" 1043 | source = "registry+https://github.com/rust-lang/crates.io-index" 1044 | checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" 1045 | dependencies = [ 1046 | "bytes", 1047 | "fnv", 1048 | "itoa", 1049 | ] 1050 | 1051 | [[package]] 1052 | name = "http-body" 1053 | version = "0.4.5" 1054 | source = "registry+https://github.com/rust-lang/crates.io-index" 1055 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" 1056 | dependencies = [ 1057 | "bytes", 1058 | "http", 1059 | "pin-project-lite", 1060 | ] 1061 | 1062 | [[package]] 1063 | name = "http-range-header" 1064 | version = "0.3.0" 1065 | source = "registry+https://github.com/rust-lang/crates.io-index" 1066 | checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" 1067 | 1068 | [[package]] 1069 | name = "httparse" 1070 | version = "1.8.0" 1071 | source = "registry+https://github.com/rust-lang/crates.io-index" 1072 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" 1073 | 1074 | [[package]] 1075 | name = "httpdate" 1076 | version = "1.0.2" 1077 | source = "registry+https://github.com/rust-lang/crates.io-index" 1078 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" 1079 | 1080 | [[package]] 1081 | name = "hyper" 1082 | version = "0.14.23" 1083 | source = "registry+https://github.com/rust-lang/crates.io-index" 1084 | checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" 1085 | dependencies = [ 1086 | "bytes", 1087 | "futures-channel", 1088 | "futures-core", 1089 | "futures-util", 1090 | "h2", 1091 | "http", 1092 | "http-body", 1093 | "httparse", 1094 | "httpdate", 1095 | "itoa", 1096 | "pin-project-lite", 1097 | "socket2", 1098 | "tokio", 1099 | "tower-service", 1100 | "tracing", 1101 | "want", 1102 | ] 1103 | 1104 | [[package]] 1105 | name = "hyper-rustls" 1106 | version = "0.23.1" 1107 | source = "registry+https://github.com/rust-lang/crates.io-index" 1108 | checksum = "59df7c4e19c950e6e0e868dcc0a300b09a9b88e9ec55bd879ca819087a77355d" 1109 | dependencies = [ 1110 | "http", 1111 | "hyper", 1112 | "rustls", 1113 | "tokio", 1114 | "tokio-rustls", 1115 | ] 1116 | 1117 | [[package]] 1118 | name = "ident_case" 1119 | version = "1.0.1" 1120 | source = "registry+https://github.com/rust-lang/crates.io-index" 1121 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 1122 | 1123 | [[package]] 1124 | name = "idna" 1125 | version = "0.3.0" 1126 | source = "registry+https://github.com/rust-lang/crates.io-index" 1127 | checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" 1128 | dependencies = [ 1129 | "unicode-bidi", 1130 | "unicode-normalization", 1131 | ] 1132 | 1133 | [[package]] 1134 | name = "include_dir" 1135 | version = "0.7.3" 1136 | source = "registry+https://github.com/rust-lang/crates.io-index" 1137 | checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" 1138 | dependencies = [ 1139 | "include_dir_macros", 1140 | ] 1141 | 1142 | [[package]] 1143 | name = "include_dir_macros" 1144 | version = "0.7.3" 1145 | source = "registry+https://github.com/rust-lang/crates.io-index" 1146 | checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" 1147 | dependencies = [ 1148 | "proc-macro2", 1149 | "quote", 1150 | ] 1151 | 1152 | [[package]] 1153 | name = "indexmap" 1154 | version = "1.9.2" 1155 | source = "registry+https://github.com/rust-lang/crates.io-index" 1156 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" 1157 | dependencies = [ 1158 | "autocfg", 1159 | "hashbrown", 1160 | "serde", 1161 | ] 1162 | 1163 | [[package]] 1164 | name = "inout" 1165 | version = "0.1.3" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" 1168 | dependencies = [ 1169 | "generic-array", 1170 | ] 1171 | 1172 | [[package]] 1173 | name = "instant" 1174 | version = "0.1.12" 1175 | source = "registry+https://github.com/rust-lang/crates.io-index" 1176 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 1177 | dependencies = [ 1178 | "cfg-if", 1179 | ] 1180 | 1181 | [[package]] 1182 | name = "io-lifetimes" 1183 | version = "1.0.3" 1184 | source = "registry+https://github.com/rust-lang/crates.io-index" 1185 | checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" 1186 | dependencies = [ 1187 | "libc", 1188 | "windows-sys", 1189 | ] 1190 | 1191 | [[package]] 1192 | name = "ipnet" 1193 | version = "2.5.1" 1194 | source = "registry+https://github.com/rust-lang/crates.io-index" 1195 | checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745" 1196 | 1197 | [[package]] 1198 | name = "is-terminal" 1199 | version = "0.4.1" 1200 | source = "registry+https://github.com/rust-lang/crates.io-index" 1201 | checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330" 1202 | dependencies = [ 1203 | "hermit-abi 0.2.6", 1204 | "io-lifetimes", 1205 | "rustix", 1206 | "windows-sys", 1207 | ] 1208 | 1209 | [[package]] 1210 | name = "itoa" 1211 | version = "1.0.4" 1212 | source = "registry+https://github.com/rust-lang/crates.io-index" 1213 | checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" 1214 | 1215 | [[package]] 1216 | name = "js-sys" 1217 | version = "0.3.60" 1218 | source = "registry+https://github.com/rust-lang/crates.io-index" 1219 | checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" 1220 | dependencies = [ 1221 | "wasm-bindgen", 1222 | ] 1223 | 1224 | [[package]] 1225 | name = "js_int" 1226 | version = "0.2.2" 1227 | source = "registry+https://github.com/rust-lang/crates.io-index" 1228 | checksum = "d937f95470b270ce8b8950207715d71aa8e153c0d44c6684d59397ed4949160a" 1229 | dependencies = [ 1230 | "serde", 1231 | ] 1232 | 1233 | [[package]] 1234 | name = "js_option" 1235 | version = "0.1.1" 1236 | source = "registry+https://github.com/rust-lang/crates.io-index" 1237 | checksum = "68421373957a1593a767013698dbf206e2b221eefe97a44d98d18672ff38423c" 1238 | dependencies = [ 1239 | "serde", 1240 | ] 1241 | 1242 | [[package]] 1243 | name = "jsonwebtoken" 1244 | version = "8.2.0" 1245 | source = "registry+https://github.com/rust-lang/crates.io-index" 1246 | checksum = "09f4f04699947111ec1733e71778d763555737579e44b85844cae8e1940a1828" 1247 | dependencies = [ 1248 | "base64", 1249 | "pem", 1250 | "ring", 1251 | "serde", 1252 | "serde_json", 1253 | "simple_asn1", 1254 | ] 1255 | 1256 | [[package]] 1257 | name = "lazy_static" 1258 | version = "1.4.0" 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" 1260 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 1261 | 1262 | [[package]] 1263 | name = "libc" 1264 | version = "0.2.138" 1265 | source = "registry+https://github.com/rust-lang/crates.io-index" 1266 | checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" 1267 | 1268 | [[package]] 1269 | name = "linux-raw-sys" 1270 | version = "0.1.3" 1271 | source = "registry+https://github.com/rust-lang/crates.io-index" 1272 | checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f" 1273 | 1274 | [[package]] 1275 | name = "lock_api" 1276 | version = "0.4.9" 1277 | source = "registry+https://github.com/rust-lang/crates.io-index" 1278 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 1279 | dependencies = [ 1280 | "autocfg", 1281 | "scopeguard", 1282 | ] 1283 | 1284 | [[package]] 1285 | name = "log" 1286 | version = "0.4.17" 1287 | source = "registry+https://github.com/rust-lang/crates.io-index" 1288 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 1289 | dependencies = [ 1290 | "cfg-if", 1291 | ] 1292 | 1293 | [[package]] 1294 | name = "lru" 1295 | version = "0.8.1" 1296 | source = "registry+https://github.com/rust-lang/crates.io-index" 1297 | checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909" 1298 | dependencies = [ 1299 | "hashbrown", 1300 | ] 1301 | 1302 | [[package]] 1303 | name = "mac" 1304 | version = "0.1.1" 1305 | source = "registry+https://github.com/rust-lang/crates.io-index" 1306 | checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" 1307 | 1308 | [[package]] 1309 | name = "maplit" 1310 | version = "1.0.2" 1311 | source = "registry+https://github.com/rust-lang/crates.io-index" 1312 | checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" 1313 | 1314 | [[package]] 1315 | name = "markup5ever" 1316 | version = "0.10.1" 1317 | source = "registry+https://github.com/rust-lang/crates.io-index" 1318 | checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd" 1319 | dependencies = [ 1320 | "log", 1321 | "phf 0.8.0", 1322 | "phf_codegen", 1323 | "string_cache", 1324 | "string_cache_codegen", 1325 | "tendril", 1326 | ] 1327 | 1328 | [[package]] 1329 | name = "matchit" 1330 | version = "0.7.0" 1331 | source = "registry+https://github.com/rust-lang/crates.io-index" 1332 | checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" 1333 | 1334 | [[package]] 1335 | name = "matrix-sdk" 1336 | version = "0.6.2" 1337 | source = "registry+https://github.com/rust-lang/crates.io-index" 1338 | checksum = "cbeafb4809f33f377165f2fbcf10e0613053ad206762194c3050a727fd3abcb2" 1339 | dependencies = [ 1340 | "anymap2", 1341 | "async-once-cell", 1342 | "async-stream", 1343 | "async-trait", 1344 | "backoff", 1345 | "bytes", 1346 | "dashmap", 1347 | "derive_builder", 1348 | "event-listener", 1349 | "futures-core", 1350 | "futures-signals", 1351 | "futures-util", 1352 | "http", 1353 | "matrix-sdk-base", 1354 | "matrix-sdk-common", 1355 | "matrix-sdk-sled", 1356 | "mime", 1357 | "reqwest", 1358 | "ruma", 1359 | "serde", 1360 | "serde_json", 1361 | "thiserror", 1362 | "tokio", 1363 | "tracing", 1364 | "url", 1365 | "wasm-timer", 1366 | "zeroize", 1367 | ] 1368 | 1369 | [[package]] 1370 | name = "matrix-sdk-base" 1371 | version = "0.6.1" 1372 | source = "registry+https://github.com/rust-lang/crates.io-index" 1373 | checksum = "b944f6d1fc8779ba790dd0b942ceff45c626c1f5da847f01122d355ad06511bd" 1374 | dependencies = [ 1375 | "async-stream", 1376 | "async-trait", 1377 | "dashmap", 1378 | "futures-channel", 1379 | "futures-core", 1380 | "futures-signals", 1381 | "futures-util", 1382 | "lru", 1383 | "matrix-sdk-common", 1384 | "once_cell", 1385 | "ruma", 1386 | "serde", 1387 | "serde_json", 1388 | "thiserror", 1389 | "tracing", 1390 | "zeroize", 1391 | ] 1392 | 1393 | [[package]] 1394 | name = "matrix-sdk-common" 1395 | version = "0.6.0" 1396 | source = "registry+https://github.com/rust-lang/crates.io-index" 1397 | checksum = "b85a6a743cc9dcf9385e61a26db78276078beddd27f3762d9d82baa2030695f1" 1398 | dependencies = [ 1399 | "async-lock", 1400 | "futures-core", 1401 | "futures-util", 1402 | "instant", 1403 | "ruma", 1404 | "serde", 1405 | "tokio", 1406 | "wasm-timer", 1407 | ] 1408 | 1409 | [[package]] 1410 | name = "matrix-sdk-sled" 1411 | version = "0.2.0" 1412 | source = "registry+https://github.com/rust-lang/crates.io-index" 1413 | checksum = "5ded5a703ad8a82b8edfde808228711315c8761a5fbf7ac2b98ab4951dadd066" 1414 | dependencies = [ 1415 | "async-stream", 1416 | "async-trait", 1417 | "dashmap", 1418 | "derive_builder", 1419 | "fs_extra", 1420 | "futures-core", 1421 | "futures-util", 1422 | "matrix-sdk-base", 1423 | "matrix-sdk-common", 1424 | "matrix-sdk-store-encryption", 1425 | "ruma", 1426 | "serde", 1427 | "serde_json", 1428 | "sled", 1429 | "thiserror", 1430 | "tokio", 1431 | "tracing", 1432 | ] 1433 | 1434 | [[package]] 1435 | name = "matrix-sdk-store-encryption" 1436 | version = "0.2.0" 1437 | source = "registry+https://github.com/rust-lang/crates.io-index" 1438 | checksum = "9ddee75c3cca58f3a323283dc4e849d19d52988903f907ed0fb53dcad5d6fd25" 1439 | dependencies = [ 1440 | "blake3", 1441 | "chacha20poly1305", 1442 | "displaydoc", 1443 | "hmac", 1444 | "pbkdf2", 1445 | "rand 0.8.5", 1446 | "serde", 1447 | "serde_json", 1448 | "sha2", 1449 | "thiserror", 1450 | "zeroize", 1451 | ] 1452 | 1453 | [[package]] 1454 | name = "memchr" 1455 | version = "2.5.0" 1456 | source = "registry+https://github.com/rust-lang/crates.io-index" 1457 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 1458 | 1459 | [[package]] 1460 | name = "memoffset" 1461 | version = "0.7.1" 1462 | source = "registry+https://github.com/rust-lang/crates.io-index" 1463 | checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" 1464 | dependencies = [ 1465 | "autocfg", 1466 | ] 1467 | 1468 | [[package]] 1469 | name = "mime" 1470 | version = "0.3.16" 1471 | source = "registry+https://github.com/rust-lang/crates.io-index" 1472 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 1473 | 1474 | [[package]] 1475 | name = "mio" 1476 | version = "0.8.5" 1477 | source = "registry+https://github.com/rust-lang/crates.io-index" 1478 | checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" 1479 | dependencies = [ 1480 | "libc", 1481 | "log", 1482 | "wasi 0.11.0+wasi-snapshot-preview1", 1483 | "windows-sys", 1484 | ] 1485 | 1486 | [[package]] 1487 | name = "morum" 1488 | version = "0.1.0" 1489 | dependencies = [ 1490 | "assign", 1491 | "async-trait", 1492 | "axum", 1493 | "axum-extra", 1494 | "clap", 1495 | "cookie", 1496 | "derive_more", 1497 | "east", 1498 | "east-build", 1499 | "east-build-helper", 1500 | "http", 1501 | "hyper", 1502 | "include_dir", 1503 | "js_int", 1504 | "jsonwebtoken", 1505 | "matrix-sdk", 1506 | "morum-base", 1507 | "morum-ui", 1508 | "pulldown-cmark", 1509 | "regex", 1510 | "ruma", 1511 | "ruma-macros", 1512 | "serde", 1513 | "serde_json", 1514 | "serde_yaml", 1515 | "thiserror", 1516 | "tokio", 1517 | "tracing", 1518 | "tracing-subscriber", 1519 | "url", 1520 | ] 1521 | 1522 | [[package]] 1523 | name = "morum-base" 1524 | version = "0.1.0" 1525 | dependencies = [ 1526 | "serde", 1527 | ] 1528 | 1529 | [[package]] 1530 | name = "morum-ui" 1531 | version = "0.1.0" 1532 | dependencies = [ 1533 | "build-helper", 1534 | "console_error_panic_hook", 1535 | "east", 1536 | "morum-base", 1537 | "serde", 1538 | "wasm-bindgen", 1539 | "web-sys", 1540 | ] 1541 | 1542 | [[package]] 1543 | name = "new_debug_unreachable" 1544 | version = "1.0.4" 1545 | source = "registry+https://github.com/rust-lang/crates.io-index" 1546 | checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" 1547 | 1548 | [[package]] 1549 | name = "nu-ansi-term" 1550 | version = "0.46.0" 1551 | source = "registry+https://github.com/rust-lang/crates.io-index" 1552 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 1553 | dependencies = [ 1554 | "overload", 1555 | "winapi", 1556 | ] 1557 | 1558 | [[package]] 1559 | name = "num-bigint" 1560 | version = "0.4.3" 1561 | source = "registry+https://github.com/rust-lang/crates.io-index" 1562 | checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" 1563 | dependencies = [ 1564 | "autocfg", 1565 | "num-integer", 1566 | "num-traits", 1567 | ] 1568 | 1569 | [[package]] 1570 | name = "num-integer" 1571 | version = "0.1.45" 1572 | source = "registry+https://github.com/rust-lang/crates.io-index" 1573 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 1574 | dependencies = [ 1575 | "autocfg", 1576 | "num-traits", 1577 | ] 1578 | 1579 | [[package]] 1580 | name = "num-traits" 1581 | version = "0.2.15" 1582 | source = "registry+https://github.com/rust-lang/crates.io-index" 1583 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 1584 | dependencies = [ 1585 | "autocfg", 1586 | ] 1587 | 1588 | [[package]] 1589 | name = "num_cpus" 1590 | version = "1.14.0" 1591 | source = "registry+https://github.com/rust-lang/crates.io-index" 1592 | checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" 1593 | dependencies = [ 1594 | "hermit-abi 0.1.19", 1595 | "libc", 1596 | ] 1597 | 1598 | [[package]] 1599 | name = "once_cell" 1600 | version = "1.16.0" 1601 | source = "registry+https://github.com/rust-lang/crates.io-index" 1602 | checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" 1603 | 1604 | [[package]] 1605 | name = "opaque-debug" 1606 | version = "0.3.0" 1607 | source = "registry+https://github.com/rust-lang/crates.io-index" 1608 | checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" 1609 | 1610 | [[package]] 1611 | name = "os_str_bytes" 1612 | version = "6.4.1" 1613 | source = "registry+https://github.com/rust-lang/crates.io-index" 1614 | checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" 1615 | 1616 | [[package]] 1617 | name = "overload" 1618 | version = "0.1.1" 1619 | source = "registry+https://github.com/rust-lang/crates.io-index" 1620 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 1621 | 1622 | [[package]] 1623 | name = "parking" 1624 | version = "2.0.0" 1625 | source = "registry+https://github.com/rust-lang/crates.io-index" 1626 | checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" 1627 | 1628 | [[package]] 1629 | name = "parking_lot" 1630 | version = "0.11.2" 1631 | source = "registry+https://github.com/rust-lang/crates.io-index" 1632 | checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" 1633 | dependencies = [ 1634 | "instant", 1635 | "lock_api", 1636 | "parking_lot_core 0.8.5", 1637 | ] 1638 | 1639 | [[package]] 1640 | name = "parking_lot" 1641 | version = "0.12.1" 1642 | source = "registry+https://github.com/rust-lang/crates.io-index" 1643 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 1644 | dependencies = [ 1645 | "lock_api", 1646 | "parking_lot_core 0.9.5", 1647 | ] 1648 | 1649 | [[package]] 1650 | name = "parking_lot_core" 1651 | version = "0.8.5" 1652 | source = "registry+https://github.com/rust-lang/crates.io-index" 1653 | checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" 1654 | dependencies = [ 1655 | "cfg-if", 1656 | "instant", 1657 | "libc", 1658 | "redox_syscall", 1659 | "smallvec", 1660 | "winapi", 1661 | ] 1662 | 1663 | [[package]] 1664 | name = "parking_lot_core" 1665 | version = "0.9.5" 1666 | source = "registry+https://github.com/rust-lang/crates.io-index" 1667 | checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" 1668 | dependencies = [ 1669 | "cfg-if", 1670 | "libc", 1671 | "redox_syscall", 1672 | "smallvec", 1673 | "windows-sys", 1674 | ] 1675 | 1676 | [[package]] 1677 | name = "password-hash" 1678 | version = "0.4.2" 1679 | source = "registry+https://github.com/rust-lang/crates.io-index" 1680 | checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" 1681 | dependencies = [ 1682 | "base64ct", 1683 | "rand_core 0.6.4", 1684 | "subtle", 1685 | ] 1686 | 1687 | [[package]] 1688 | name = "paste" 1689 | version = "1.0.9" 1690 | source = "registry+https://github.com/rust-lang/crates.io-index" 1691 | checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" 1692 | 1693 | [[package]] 1694 | name = "pbkdf2" 1695 | version = "0.11.0" 1696 | source = "registry+https://github.com/rust-lang/crates.io-index" 1697 | checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" 1698 | dependencies = [ 1699 | "digest", 1700 | "hmac", 1701 | "password-hash", 1702 | "sha2", 1703 | ] 1704 | 1705 | [[package]] 1706 | name = "pem" 1707 | version = "1.1.0" 1708 | source = "registry+https://github.com/rust-lang/crates.io-index" 1709 | checksum = "03c64931a1a212348ec4f3b4362585eca7159d0d09cbdf4a7f74f02173596fd4" 1710 | dependencies = [ 1711 | "base64", 1712 | ] 1713 | 1714 | [[package]] 1715 | name = "percent-encoding" 1716 | version = "2.2.0" 1717 | source = "registry+https://github.com/rust-lang/crates.io-index" 1718 | checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" 1719 | 1720 | [[package]] 1721 | name = "phf" 1722 | version = "0.8.0" 1723 | source = "registry+https://github.com/rust-lang/crates.io-index" 1724 | checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" 1725 | dependencies = [ 1726 | "phf_shared 0.8.0", 1727 | ] 1728 | 1729 | [[package]] 1730 | name = "phf" 1731 | version = "0.10.1" 1732 | source = "registry+https://github.com/rust-lang/crates.io-index" 1733 | checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" 1734 | dependencies = [ 1735 | "phf_macros", 1736 | "phf_shared 0.10.0", 1737 | "proc-macro-hack", 1738 | ] 1739 | 1740 | [[package]] 1741 | name = "phf_codegen" 1742 | version = "0.8.0" 1743 | source = "registry+https://github.com/rust-lang/crates.io-index" 1744 | checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" 1745 | dependencies = [ 1746 | "phf_generator 0.8.0", 1747 | "phf_shared 0.8.0", 1748 | ] 1749 | 1750 | [[package]] 1751 | name = "phf_generator" 1752 | version = "0.8.0" 1753 | source = "registry+https://github.com/rust-lang/crates.io-index" 1754 | checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" 1755 | dependencies = [ 1756 | "phf_shared 0.8.0", 1757 | "rand 0.7.3", 1758 | ] 1759 | 1760 | [[package]] 1761 | name = "phf_generator" 1762 | version = "0.10.0" 1763 | source = "registry+https://github.com/rust-lang/crates.io-index" 1764 | checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" 1765 | dependencies = [ 1766 | "phf_shared 0.10.0", 1767 | "rand 0.8.5", 1768 | ] 1769 | 1770 | [[package]] 1771 | name = "phf_macros" 1772 | version = "0.10.0" 1773 | source = "registry+https://github.com/rust-lang/crates.io-index" 1774 | checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" 1775 | dependencies = [ 1776 | "phf_generator 0.10.0", 1777 | "phf_shared 0.10.0", 1778 | "proc-macro-hack", 1779 | "proc-macro2", 1780 | "quote", 1781 | "syn", 1782 | ] 1783 | 1784 | [[package]] 1785 | name = "phf_shared" 1786 | version = "0.8.0" 1787 | source = "registry+https://github.com/rust-lang/crates.io-index" 1788 | checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" 1789 | dependencies = [ 1790 | "siphasher", 1791 | ] 1792 | 1793 | [[package]] 1794 | name = "phf_shared" 1795 | version = "0.10.0" 1796 | source = "registry+https://github.com/rust-lang/crates.io-index" 1797 | checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" 1798 | dependencies = [ 1799 | "siphasher", 1800 | ] 1801 | 1802 | [[package]] 1803 | name = "pin-project" 1804 | version = "1.0.12" 1805 | source = "registry+https://github.com/rust-lang/crates.io-index" 1806 | checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" 1807 | dependencies = [ 1808 | "pin-project-internal", 1809 | ] 1810 | 1811 | [[package]] 1812 | name = "pin-project-internal" 1813 | version = "1.0.12" 1814 | source = "registry+https://github.com/rust-lang/crates.io-index" 1815 | checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" 1816 | dependencies = [ 1817 | "proc-macro2", 1818 | "quote", 1819 | "syn", 1820 | ] 1821 | 1822 | [[package]] 1823 | name = "pin-project-lite" 1824 | version = "0.2.9" 1825 | source = "registry+https://github.com/rust-lang/crates.io-index" 1826 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 1827 | 1828 | [[package]] 1829 | name = "pin-utils" 1830 | version = "0.1.0" 1831 | source = "registry+https://github.com/rust-lang/crates.io-index" 1832 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1833 | 1834 | [[package]] 1835 | name = "poly1305" 1836 | version = "0.7.2" 1837 | source = "registry+https://github.com/rust-lang/crates.io-index" 1838 | checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" 1839 | dependencies = [ 1840 | "cpufeatures", 1841 | "opaque-debug", 1842 | "universal-hash 0.4.1", 1843 | ] 1844 | 1845 | [[package]] 1846 | name = "polyval" 1847 | version = "0.6.0" 1848 | source = "registry+https://github.com/rust-lang/crates.io-index" 1849 | checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6" 1850 | dependencies = [ 1851 | "cfg-if", 1852 | "cpufeatures", 1853 | "opaque-debug", 1854 | "universal-hash 0.5.0", 1855 | ] 1856 | 1857 | [[package]] 1858 | name = "ppv-lite86" 1859 | version = "0.2.17" 1860 | source = "registry+https://github.com/rust-lang/crates.io-index" 1861 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 1862 | 1863 | [[package]] 1864 | name = "precomputed-hash" 1865 | version = "0.1.1" 1866 | source = "registry+https://github.com/rust-lang/crates.io-index" 1867 | checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" 1868 | 1869 | [[package]] 1870 | name = "proc-macro-crate" 1871 | version = "1.2.1" 1872 | source = "registry+https://github.com/rust-lang/crates.io-index" 1873 | checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" 1874 | dependencies = [ 1875 | "once_cell", 1876 | "thiserror", 1877 | "toml", 1878 | ] 1879 | 1880 | [[package]] 1881 | name = "proc-macro-error" 1882 | version = "1.0.4" 1883 | source = "registry+https://github.com/rust-lang/crates.io-index" 1884 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 1885 | dependencies = [ 1886 | "proc-macro-error-attr", 1887 | "proc-macro2", 1888 | "quote", 1889 | "syn", 1890 | "version_check", 1891 | ] 1892 | 1893 | [[package]] 1894 | name = "proc-macro-error-attr" 1895 | version = "1.0.4" 1896 | source = "registry+https://github.com/rust-lang/crates.io-index" 1897 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 1898 | dependencies = [ 1899 | "proc-macro2", 1900 | "quote", 1901 | "version_check", 1902 | ] 1903 | 1904 | [[package]] 1905 | name = "proc-macro-hack" 1906 | version = "0.5.19" 1907 | source = "registry+https://github.com/rust-lang/crates.io-index" 1908 | checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" 1909 | 1910 | [[package]] 1911 | name = "proc-macro2" 1912 | version = "1.0.47" 1913 | source = "registry+https://github.com/rust-lang/crates.io-index" 1914 | checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" 1915 | dependencies = [ 1916 | "unicode-ident", 1917 | ] 1918 | 1919 | [[package]] 1920 | name = "pulldown-cmark" 1921 | version = "0.9.2" 1922 | source = "registry+https://github.com/rust-lang/crates.io-index" 1923 | checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63" 1924 | dependencies = [ 1925 | "bitflags", 1926 | "getopts", 1927 | "memchr", 1928 | "unicase", 1929 | ] 1930 | 1931 | [[package]] 1932 | name = "quote" 1933 | version = "1.0.21" 1934 | source = "registry+https://github.com/rust-lang/crates.io-index" 1935 | checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" 1936 | dependencies = [ 1937 | "proc-macro2", 1938 | ] 1939 | 1940 | [[package]] 1941 | name = "rand" 1942 | version = "0.7.3" 1943 | source = "registry+https://github.com/rust-lang/crates.io-index" 1944 | checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" 1945 | dependencies = [ 1946 | "getrandom 0.1.16", 1947 | "libc", 1948 | "rand_chacha 0.2.2", 1949 | "rand_core 0.5.1", 1950 | "rand_hc", 1951 | "rand_pcg", 1952 | ] 1953 | 1954 | [[package]] 1955 | name = "rand" 1956 | version = "0.8.5" 1957 | source = "registry+https://github.com/rust-lang/crates.io-index" 1958 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1959 | dependencies = [ 1960 | "libc", 1961 | "rand_chacha 0.3.1", 1962 | "rand_core 0.6.4", 1963 | ] 1964 | 1965 | [[package]] 1966 | name = "rand_chacha" 1967 | version = "0.2.2" 1968 | source = "registry+https://github.com/rust-lang/crates.io-index" 1969 | checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" 1970 | dependencies = [ 1971 | "ppv-lite86", 1972 | "rand_core 0.5.1", 1973 | ] 1974 | 1975 | [[package]] 1976 | name = "rand_chacha" 1977 | version = "0.3.1" 1978 | source = "registry+https://github.com/rust-lang/crates.io-index" 1979 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1980 | dependencies = [ 1981 | "ppv-lite86", 1982 | "rand_core 0.6.4", 1983 | ] 1984 | 1985 | [[package]] 1986 | name = "rand_core" 1987 | version = "0.5.1" 1988 | source = "registry+https://github.com/rust-lang/crates.io-index" 1989 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 1990 | dependencies = [ 1991 | "getrandom 0.1.16", 1992 | ] 1993 | 1994 | [[package]] 1995 | name = "rand_core" 1996 | version = "0.6.4" 1997 | source = "registry+https://github.com/rust-lang/crates.io-index" 1998 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1999 | dependencies = [ 2000 | "getrandom 0.2.8", 2001 | ] 2002 | 2003 | [[package]] 2004 | name = "rand_hc" 2005 | version = "0.2.0" 2006 | source = "registry+https://github.com/rust-lang/crates.io-index" 2007 | checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" 2008 | dependencies = [ 2009 | "rand_core 0.5.1", 2010 | ] 2011 | 2012 | [[package]] 2013 | name = "rand_pcg" 2014 | version = "0.2.1" 2015 | source = "registry+https://github.com/rust-lang/crates.io-index" 2016 | checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" 2017 | dependencies = [ 2018 | "rand_core 0.5.1", 2019 | ] 2020 | 2021 | [[package]] 2022 | name = "redox_syscall" 2023 | version = "0.2.16" 2024 | source = "registry+https://github.com/rust-lang/crates.io-index" 2025 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 2026 | dependencies = [ 2027 | "bitflags", 2028 | ] 2029 | 2030 | [[package]] 2031 | name = "regex" 2032 | version = "1.7.0" 2033 | source = "registry+https://github.com/rust-lang/crates.io-index" 2034 | checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" 2035 | dependencies = [ 2036 | "aho-corasick", 2037 | "memchr", 2038 | "regex-syntax", 2039 | ] 2040 | 2041 | [[package]] 2042 | name = "regex-syntax" 2043 | version = "0.6.28" 2044 | source = "registry+https://github.com/rust-lang/crates.io-index" 2045 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" 2046 | 2047 | [[package]] 2048 | name = "reqwest" 2049 | version = "0.11.13" 2050 | source = "registry+https://github.com/rust-lang/crates.io-index" 2051 | checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" 2052 | dependencies = [ 2053 | "base64", 2054 | "bytes", 2055 | "encoding_rs", 2056 | "futures-core", 2057 | "futures-util", 2058 | "h2", 2059 | "http", 2060 | "http-body", 2061 | "hyper", 2062 | "hyper-rustls", 2063 | "ipnet", 2064 | "js-sys", 2065 | "log", 2066 | "mime", 2067 | "once_cell", 2068 | "percent-encoding", 2069 | "pin-project-lite", 2070 | "rustls", 2071 | "rustls-pemfile", 2072 | "serde", 2073 | "serde_json", 2074 | "serde_urlencoded", 2075 | "tokio", 2076 | "tokio-rustls", 2077 | "tower-service", 2078 | "url", 2079 | "wasm-bindgen", 2080 | "wasm-bindgen-futures", 2081 | "web-sys", 2082 | "webpki-roots", 2083 | "winreg", 2084 | ] 2085 | 2086 | [[package]] 2087 | name = "ring" 2088 | version = "0.16.20" 2089 | source = "registry+https://github.com/rust-lang/crates.io-index" 2090 | checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" 2091 | dependencies = [ 2092 | "cc", 2093 | "libc", 2094 | "once_cell", 2095 | "spin", 2096 | "untrusted", 2097 | "web-sys", 2098 | "winapi", 2099 | ] 2100 | 2101 | [[package]] 2102 | name = "ruma" 2103 | version = "0.7.4" 2104 | source = "registry+https://github.com/rust-lang/crates.io-index" 2105 | checksum = "8dc348e3a4a18abc4e97fffa5e2e623f6edd50ba3a1dd5f47eb249fea713b69f" 2106 | dependencies = [ 2107 | "assign", 2108 | "js_int", 2109 | "js_option", 2110 | "ruma-appservice-api", 2111 | "ruma-client", 2112 | "ruma-client-api", 2113 | "ruma-common", 2114 | "ruma-federation-api", 2115 | ] 2116 | 2117 | [[package]] 2118 | name = "ruma-appservice-api" 2119 | version = "0.7.0" 2120 | source = "registry+https://github.com/rust-lang/crates.io-index" 2121 | checksum = "d4f8cecdd4e2729656fc4126b6b5b218834d4025e0ed0e5063087a0231098a5c" 2122 | dependencies = [ 2123 | "ruma-common", 2124 | "serde", 2125 | "serde_json", 2126 | ] 2127 | 2128 | [[package]] 2129 | name = "ruma-client" 2130 | version = "0.10.0" 2131 | source = "registry+https://github.com/rust-lang/crates.io-index" 2132 | checksum = "4ea98d70ccfa3ec8fae504312524d044de982215c293758f502a315bd927b063" 2133 | dependencies = [ 2134 | "assign", 2135 | "async-stream", 2136 | "async-trait", 2137 | "bytes", 2138 | "futures-core", 2139 | "http", 2140 | "reqwest", 2141 | "ruma-common", 2142 | "serde", 2143 | "serde_json", 2144 | "tracing", 2145 | ] 2146 | 2147 | [[package]] 2148 | name = "ruma-client-api" 2149 | version = "0.15.3" 2150 | source = "registry+https://github.com/rust-lang/crates.io-index" 2151 | checksum = "d1e72bc731b4dc8b569aa83915f13e419144b67110d858c65bb74aa05e2dc4b7" 2152 | dependencies = [ 2153 | "assign", 2154 | "bytes", 2155 | "http", 2156 | "js_int", 2157 | "maplit", 2158 | "percent-encoding", 2159 | "ruma-common", 2160 | "serde", 2161 | "serde_json", 2162 | ] 2163 | 2164 | [[package]] 2165 | name = "ruma-common" 2166 | version = "0.10.5" 2167 | source = "registry+https://github.com/rust-lang/crates.io-index" 2168 | checksum = "716889595f4edc3cfeb94d9f122e413f73e37d7d80ea1c14196e1004241a3889" 2169 | dependencies = [ 2170 | "base64", 2171 | "bytes", 2172 | "form_urlencoded", 2173 | "html5ever", 2174 | "http", 2175 | "indexmap", 2176 | "itoa", 2177 | "js_int", 2178 | "js_option", 2179 | "percent-encoding", 2180 | "phf 0.10.1", 2181 | "rand 0.8.5", 2182 | "regex", 2183 | "ruma-identifiers-validation", 2184 | "ruma-macros", 2185 | "serde", 2186 | "serde_json", 2187 | "thiserror", 2188 | "tracing", 2189 | "url", 2190 | "uuid", 2191 | "wildmatch", 2192 | ] 2193 | 2194 | [[package]] 2195 | name = "ruma-federation-api" 2196 | version = "0.6.0" 2197 | source = "registry+https://github.com/rust-lang/crates.io-index" 2198 | checksum = "9f905d12f6144c7a754bd0339fa6893698c03d03a908abb20cc6eeb4ec7f9466" 2199 | dependencies = [ 2200 | "js_int", 2201 | "ruma-common", 2202 | "serde", 2203 | "serde_json", 2204 | ] 2205 | 2206 | [[package]] 2207 | name = "ruma-identifiers-validation" 2208 | version = "0.9.0" 2209 | source = "registry+https://github.com/rust-lang/crates.io-index" 2210 | checksum = "eabac62d16465a87435579c779d74dceabb93b09e44c766af6085050f3cc4275" 2211 | dependencies = [ 2212 | "js_int", 2213 | "thiserror", 2214 | ] 2215 | 2216 | [[package]] 2217 | name = "ruma-macros" 2218 | version = "0.10.5" 2219 | source = "registry+https://github.com/rust-lang/crates.io-index" 2220 | checksum = "0f82e91eb61cd86d9287303133ee55b54618eccb75a522cc22a42c15f5bda340" 2221 | dependencies = [ 2222 | "once_cell", 2223 | "proc-macro-crate", 2224 | "proc-macro2", 2225 | "quote", 2226 | "ruma-identifiers-validation", 2227 | "serde", 2228 | "syn", 2229 | "toml", 2230 | ] 2231 | 2232 | [[package]] 2233 | name = "rustc_version" 2234 | version = "0.4.0" 2235 | source = "registry+https://github.com/rust-lang/crates.io-index" 2236 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 2237 | dependencies = [ 2238 | "semver 1.0.14", 2239 | ] 2240 | 2241 | [[package]] 2242 | name = "rustix" 2243 | version = "0.36.4" 2244 | source = "registry+https://github.com/rust-lang/crates.io-index" 2245 | checksum = "cb93e85278e08bb5788653183213d3a60fc242b10cb9be96586f5a73dcb67c23" 2246 | dependencies = [ 2247 | "bitflags", 2248 | "errno", 2249 | "io-lifetimes", 2250 | "libc", 2251 | "linux-raw-sys", 2252 | "windows-sys", 2253 | ] 2254 | 2255 | [[package]] 2256 | name = "rustls" 2257 | version = "0.20.7" 2258 | source = "registry+https://github.com/rust-lang/crates.io-index" 2259 | checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c" 2260 | dependencies = [ 2261 | "log", 2262 | "ring", 2263 | "sct", 2264 | "webpki", 2265 | ] 2266 | 2267 | [[package]] 2268 | name = "rustls-pemfile" 2269 | version = "1.0.1" 2270 | source = "registry+https://github.com/rust-lang/crates.io-index" 2271 | checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" 2272 | dependencies = [ 2273 | "base64", 2274 | ] 2275 | 2276 | [[package]] 2277 | name = "rustversion" 2278 | version = "1.0.9" 2279 | source = "registry+https://github.com/rust-lang/crates.io-index" 2280 | checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" 2281 | 2282 | [[package]] 2283 | name = "ryu" 2284 | version = "1.0.11" 2285 | source = "registry+https://github.com/rust-lang/crates.io-index" 2286 | checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" 2287 | 2288 | [[package]] 2289 | name = "scopeguard" 2290 | version = "1.1.0" 2291 | source = "registry+https://github.com/rust-lang/crates.io-index" 2292 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 2293 | 2294 | [[package]] 2295 | name = "sct" 2296 | version = "0.7.0" 2297 | source = "registry+https://github.com/rust-lang/crates.io-index" 2298 | checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" 2299 | dependencies = [ 2300 | "ring", 2301 | "untrusted", 2302 | ] 2303 | 2304 | [[package]] 2305 | name = "semver" 2306 | version = "0.6.0" 2307 | source = "registry+https://github.com/rust-lang/crates.io-index" 2308 | checksum = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" 2309 | dependencies = [ 2310 | "semver-parser", 2311 | ] 2312 | 2313 | [[package]] 2314 | name = "semver" 2315 | version = "1.0.14" 2316 | source = "registry+https://github.com/rust-lang/crates.io-index" 2317 | checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" 2318 | 2319 | [[package]] 2320 | name = "semver-parser" 2321 | version = "0.7.0" 2322 | source = "registry+https://github.com/rust-lang/crates.io-index" 2323 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 2324 | 2325 | [[package]] 2326 | name = "serde" 2327 | version = "1.0.148" 2328 | source = "registry+https://github.com/rust-lang/crates.io-index" 2329 | checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc" 2330 | dependencies = [ 2331 | "serde_derive", 2332 | ] 2333 | 2334 | [[package]] 2335 | name = "serde_derive" 2336 | version = "1.0.148" 2337 | source = "registry+https://github.com/rust-lang/crates.io-index" 2338 | checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c" 2339 | dependencies = [ 2340 | "proc-macro2", 2341 | "quote", 2342 | "syn", 2343 | ] 2344 | 2345 | [[package]] 2346 | name = "serde_json" 2347 | version = "1.0.89" 2348 | source = "registry+https://github.com/rust-lang/crates.io-index" 2349 | checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" 2350 | dependencies = [ 2351 | "itoa", 2352 | "ryu", 2353 | "serde", 2354 | ] 2355 | 2356 | [[package]] 2357 | name = "serde_path_to_error" 2358 | version = "0.1.8" 2359 | source = "registry+https://github.com/rust-lang/crates.io-index" 2360 | checksum = "184c643044780f7ceb59104cef98a5a6f12cb2288a7bc701ab93a362b49fd47d" 2361 | dependencies = [ 2362 | "serde", 2363 | ] 2364 | 2365 | [[package]] 2366 | name = "serde_urlencoded" 2367 | version = "0.7.1" 2368 | source = "registry+https://github.com/rust-lang/crates.io-index" 2369 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 2370 | dependencies = [ 2371 | "form_urlencoded", 2372 | "itoa", 2373 | "ryu", 2374 | "serde", 2375 | ] 2376 | 2377 | [[package]] 2378 | name = "serde_yaml" 2379 | version = "0.9.14" 2380 | source = "registry+https://github.com/rust-lang/crates.io-index" 2381 | checksum = "6d232d893b10de3eb7258ff01974d6ee20663d8e833263c99409d4b13a0209da" 2382 | dependencies = [ 2383 | "indexmap", 2384 | "itoa", 2385 | "ryu", 2386 | "serde", 2387 | "unsafe-libyaml", 2388 | ] 2389 | 2390 | [[package]] 2391 | name = "sha1" 2392 | version = "0.10.5" 2393 | source = "registry+https://github.com/rust-lang/crates.io-index" 2394 | checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" 2395 | dependencies = [ 2396 | "cfg-if", 2397 | "cpufeatures", 2398 | "digest", 2399 | ] 2400 | 2401 | [[package]] 2402 | name = "sha2" 2403 | version = "0.10.6" 2404 | source = "registry+https://github.com/rust-lang/crates.io-index" 2405 | checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" 2406 | dependencies = [ 2407 | "cfg-if", 2408 | "cpufeatures", 2409 | "digest", 2410 | ] 2411 | 2412 | [[package]] 2413 | name = "sharded-slab" 2414 | version = "0.1.4" 2415 | source = "registry+https://github.com/rust-lang/crates.io-index" 2416 | checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" 2417 | dependencies = [ 2418 | "lazy_static", 2419 | ] 2420 | 2421 | [[package]] 2422 | name = "signal-hook-registry" 2423 | version = "1.4.0" 2424 | source = "registry+https://github.com/rust-lang/crates.io-index" 2425 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 2426 | dependencies = [ 2427 | "libc", 2428 | ] 2429 | 2430 | [[package]] 2431 | name = "simple_asn1" 2432 | version = "0.6.2" 2433 | source = "registry+https://github.com/rust-lang/crates.io-index" 2434 | checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" 2435 | dependencies = [ 2436 | "num-bigint", 2437 | "num-traits", 2438 | "thiserror", 2439 | "time", 2440 | ] 2441 | 2442 | [[package]] 2443 | name = "siphasher" 2444 | version = "0.3.10" 2445 | source = "registry+https://github.com/rust-lang/crates.io-index" 2446 | checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" 2447 | 2448 | [[package]] 2449 | name = "slab" 2450 | version = "0.4.7" 2451 | source = "registry+https://github.com/rust-lang/crates.io-index" 2452 | checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" 2453 | dependencies = [ 2454 | "autocfg", 2455 | ] 2456 | 2457 | [[package]] 2458 | name = "sled" 2459 | version = "0.34.7" 2460 | source = "registry+https://github.com/rust-lang/crates.io-index" 2461 | checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" 2462 | dependencies = [ 2463 | "crc32fast", 2464 | "crossbeam-epoch", 2465 | "crossbeam-utils", 2466 | "fs2", 2467 | "fxhash", 2468 | "libc", 2469 | "log", 2470 | "parking_lot 0.11.2", 2471 | ] 2472 | 2473 | [[package]] 2474 | name = "slotmap" 2475 | version = "1.0.6" 2476 | source = "registry+https://github.com/rust-lang/crates.io-index" 2477 | checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" 2478 | dependencies = [ 2479 | "version_check", 2480 | ] 2481 | 2482 | [[package]] 2483 | name = "smallvec" 2484 | version = "1.10.0" 2485 | source = "registry+https://github.com/rust-lang/crates.io-index" 2486 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 2487 | 2488 | [[package]] 2489 | name = "socket2" 2490 | version = "0.4.7" 2491 | source = "registry+https://github.com/rust-lang/crates.io-index" 2492 | checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" 2493 | dependencies = [ 2494 | "libc", 2495 | "winapi", 2496 | ] 2497 | 2498 | [[package]] 2499 | name = "spin" 2500 | version = "0.5.2" 2501 | source = "registry+https://github.com/rust-lang/crates.io-index" 2502 | checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" 2503 | 2504 | [[package]] 2505 | name = "string_cache" 2506 | version = "0.8.4" 2507 | source = "registry+https://github.com/rust-lang/crates.io-index" 2508 | checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" 2509 | dependencies = [ 2510 | "new_debug_unreachable", 2511 | "once_cell", 2512 | "parking_lot 0.12.1", 2513 | "phf_shared 0.10.0", 2514 | "precomputed-hash", 2515 | "serde", 2516 | ] 2517 | 2518 | [[package]] 2519 | name = "string_cache_codegen" 2520 | version = "0.5.2" 2521 | source = "registry+https://github.com/rust-lang/crates.io-index" 2522 | checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" 2523 | dependencies = [ 2524 | "phf_generator 0.10.0", 2525 | "phf_shared 0.10.0", 2526 | "proc-macro2", 2527 | "quote", 2528 | ] 2529 | 2530 | [[package]] 2531 | name = "strsim" 2532 | version = "0.10.0" 2533 | source = "registry+https://github.com/rust-lang/crates.io-index" 2534 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 2535 | 2536 | [[package]] 2537 | name = "subtle" 2538 | version = "2.4.1" 2539 | source = "registry+https://github.com/rust-lang/crates.io-index" 2540 | checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" 2541 | 2542 | [[package]] 2543 | name = "sycamore" 2544 | version = "0.8.2" 2545 | source = "registry+https://github.com/rust-lang/crates.io-index" 2546 | checksum = "67817393b3c9828db84614f64db9a1ebb94729ce3a3751c41e7ff23d3f8e7f00" 2547 | dependencies = [ 2548 | "ahash", 2549 | "html-escape", 2550 | "indexmap", 2551 | "js-sys", 2552 | "once_cell", 2553 | "paste", 2554 | "sycamore-core", 2555 | "sycamore-macro", 2556 | "sycamore-reactive", 2557 | "sycamore-web", 2558 | "wasm-bindgen", 2559 | "web-sys", 2560 | ] 2561 | 2562 | [[package]] 2563 | name = "sycamore-core" 2564 | version = "0.8.2" 2565 | source = "registry+https://github.com/rust-lang/crates.io-index" 2566 | checksum = "2dce7f0440c5ea2b74a544deb5423708c023fade36e63515423d3f3ab5e1a998" 2567 | dependencies = [ 2568 | "ahash", 2569 | "sycamore-reactive", 2570 | ] 2571 | 2572 | [[package]] 2573 | name = "sycamore-macro" 2574 | version = "0.8.2" 2575 | source = "registry+https://github.com/rust-lang/crates.io-index" 2576 | checksum = "8f3abd3f402c1a943cf70860b91a40c79c713e269156445998dbfd647deac8a5" 2577 | dependencies = [ 2578 | "once_cell", 2579 | "proc-macro2", 2580 | "quote", 2581 | "syn", 2582 | ] 2583 | 2584 | [[package]] 2585 | name = "sycamore-reactive" 2586 | version = "0.8.1" 2587 | source = "registry+https://github.com/rust-lang/crates.io-index" 2588 | checksum = "6376b578ad32f5f3ab6943bccec906fb0e1f0258a8bedf811afdec8c3330ef80" 2589 | dependencies = [ 2590 | "ahash", 2591 | "bumpalo", 2592 | "indexmap", 2593 | "slotmap", 2594 | "smallvec", 2595 | ] 2596 | 2597 | [[package]] 2598 | name = "sycamore-web" 2599 | version = "0.8.2" 2600 | source = "registry+https://github.com/rust-lang/crates.io-index" 2601 | checksum = "6db9520735f765e60718df8125eb27db19b990bed1116c9b3e8aae374dde1fe8" 2602 | dependencies = [ 2603 | "html-escape", 2604 | "indexmap", 2605 | "js-sys", 2606 | "once_cell", 2607 | "sycamore-core", 2608 | "sycamore-reactive", 2609 | "wasm-bindgen", 2610 | "web-sys", 2611 | ] 2612 | 2613 | [[package]] 2614 | name = "syn" 2615 | version = "1.0.105" 2616 | source = "registry+https://github.com/rust-lang/crates.io-index" 2617 | checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" 2618 | dependencies = [ 2619 | "proc-macro2", 2620 | "quote", 2621 | "unicode-ident", 2622 | ] 2623 | 2624 | [[package]] 2625 | name = "sync_wrapper" 2626 | version = "0.1.1" 2627 | source = "registry+https://github.com/rust-lang/crates.io-index" 2628 | checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" 2629 | 2630 | [[package]] 2631 | name = "synstructure" 2632 | version = "0.12.6" 2633 | source = "registry+https://github.com/rust-lang/crates.io-index" 2634 | checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" 2635 | dependencies = [ 2636 | "proc-macro2", 2637 | "quote", 2638 | "syn", 2639 | "unicode-xid", 2640 | ] 2641 | 2642 | [[package]] 2643 | name = "tendril" 2644 | version = "0.4.3" 2645 | source = "registry+https://github.com/rust-lang/crates.io-index" 2646 | checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" 2647 | dependencies = [ 2648 | "futf", 2649 | "mac", 2650 | "utf-8", 2651 | ] 2652 | 2653 | [[package]] 2654 | name = "termcolor" 2655 | version = "1.1.3" 2656 | source = "registry+https://github.com/rust-lang/crates.io-index" 2657 | checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" 2658 | dependencies = [ 2659 | "winapi-util", 2660 | ] 2661 | 2662 | [[package]] 2663 | name = "thiserror" 2664 | version = "1.0.37" 2665 | source = "registry+https://github.com/rust-lang/crates.io-index" 2666 | checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" 2667 | dependencies = [ 2668 | "thiserror-impl", 2669 | ] 2670 | 2671 | [[package]] 2672 | name = "thiserror-impl" 2673 | version = "1.0.37" 2674 | source = "registry+https://github.com/rust-lang/crates.io-index" 2675 | checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" 2676 | dependencies = [ 2677 | "proc-macro2", 2678 | "quote", 2679 | "syn", 2680 | ] 2681 | 2682 | [[package]] 2683 | name = "thread_local" 2684 | version = "1.1.4" 2685 | source = "registry+https://github.com/rust-lang/crates.io-index" 2686 | checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" 2687 | dependencies = [ 2688 | "once_cell", 2689 | ] 2690 | 2691 | [[package]] 2692 | name = "time" 2693 | version = "0.3.17" 2694 | source = "registry+https://github.com/rust-lang/crates.io-index" 2695 | checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" 2696 | dependencies = [ 2697 | "itoa", 2698 | "serde", 2699 | "time-core", 2700 | "time-macros", 2701 | ] 2702 | 2703 | [[package]] 2704 | name = "time-core" 2705 | version = "0.1.0" 2706 | source = "registry+https://github.com/rust-lang/crates.io-index" 2707 | checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" 2708 | 2709 | [[package]] 2710 | name = "time-macros" 2711 | version = "0.2.6" 2712 | source = "registry+https://github.com/rust-lang/crates.io-index" 2713 | checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" 2714 | dependencies = [ 2715 | "time-core", 2716 | ] 2717 | 2718 | [[package]] 2719 | name = "tinyvec" 2720 | version = "1.6.0" 2721 | source = "registry+https://github.com/rust-lang/crates.io-index" 2722 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 2723 | dependencies = [ 2724 | "tinyvec_macros", 2725 | ] 2726 | 2727 | [[package]] 2728 | name = "tinyvec_macros" 2729 | version = "0.1.0" 2730 | source = "registry+https://github.com/rust-lang/crates.io-index" 2731 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 2732 | 2733 | [[package]] 2734 | name = "tokio" 2735 | version = "1.22.0" 2736 | source = "registry+https://github.com/rust-lang/crates.io-index" 2737 | checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3" 2738 | dependencies = [ 2739 | "autocfg", 2740 | "bytes", 2741 | "libc", 2742 | "memchr", 2743 | "mio", 2744 | "num_cpus", 2745 | "parking_lot 0.12.1", 2746 | "pin-project-lite", 2747 | "signal-hook-registry", 2748 | "socket2", 2749 | "tokio-macros", 2750 | "winapi", 2751 | ] 2752 | 2753 | [[package]] 2754 | name = "tokio-macros" 2755 | version = "1.8.2" 2756 | source = "registry+https://github.com/rust-lang/crates.io-index" 2757 | checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" 2758 | dependencies = [ 2759 | "proc-macro2", 2760 | "quote", 2761 | "syn", 2762 | ] 2763 | 2764 | [[package]] 2765 | name = "tokio-rustls" 2766 | version = "0.23.4" 2767 | source = "registry+https://github.com/rust-lang/crates.io-index" 2768 | checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" 2769 | dependencies = [ 2770 | "rustls", 2771 | "tokio", 2772 | "webpki", 2773 | ] 2774 | 2775 | [[package]] 2776 | name = "tokio-util" 2777 | version = "0.7.4" 2778 | source = "registry+https://github.com/rust-lang/crates.io-index" 2779 | checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" 2780 | dependencies = [ 2781 | "bytes", 2782 | "futures-core", 2783 | "futures-sink", 2784 | "pin-project-lite", 2785 | "tokio", 2786 | "tracing", 2787 | ] 2788 | 2789 | [[package]] 2790 | name = "toml" 2791 | version = "0.5.9" 2792 | source = "registry+https://github.com/rust-lang/crates.io-index" 2793 | checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" 2794 | dependencies = [ 2795 | "serde", 2796 | ] 2797 | 2798 | [[package]] 2799 | name = "tower" 2800 | version = "0.4.13" 2801 | source = "registry+https://github.com/rust-lang/crates.io-index" 2802 | checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" 2803 | dependencies = [ 2804 | "futures-core", 2805 | "futures-util", 2806 | "pin-project", 2807 | "pin-project-lite", 2808 | "tokio", 2809 | "tower-layer", 2810 | "tower-service", 2811 | "tracing", 2812 | ] 2813 | 2814 | [[package]] 2815 | name = "tower-http" 2816 | version = "0.3.5" 2817 | source = "registry+https://github.com/rust-lang/crates.io-index" 2818 | checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" 2819 | dependencies = [ 2820 | "bitflags", 2821 | "bytes", 2822 | "futures-core", 2823 | "futures-util", 2824 | "http", 2825 | "http-body", 2826 | "http-range-header", 2827 | "pin-project-lite", 2828 | "tower", 2829 | "tower-layer", 2830 | "tower-service", 2831 | ] 2832 | 2833 | [[package]] 2834 | name = "tower-layer" 2835 | version = "0.3.2" 2836 | source = "registry+https://github.com/rust-lang/crates.io-index" 2837 | checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" 2838 | 2839 | [[package]] 2840 | name = "tower-service" 2841 | version = "0.3.2" 2842 | source = "registry+https://github.com/rust-lang/crates.io-index" 2843 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 2844 | 2845 | [[package]] 2846 | name = "tracing" 2847 | version = "0.1.37" 2848 | source = "registry+https://github.com/rust-lang/crates.io-index" 2849 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 2850 | dependencies = [ 2851 | "cfg-if", 2852 | "log", 2853 | "pin-project-lite", 2854 | "tracing-attributes", 2855 | "tracing-core", 2856 | ] 2857 | 2858 | [[package]] 2859 | name = "tracing-attributes" 2860 | version = "0.1.23" 2861 | source = "registry+https://github.com/rust-lang/crates.io-index" 2862 | checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" 2863 | dependencies = [ 2864 | "proc-macro2", 2865 | "quote", 2866 | "syn", 2867 | ] 2868 | 2869 | [[package]] 2870 | name = "tracing-core" 2871 | version = "0.1.30" 2872 | source = "registry+https://github.com/rust-lang/crates.io-index" 2873 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" 2874 | dependencies = [ 2875 | "once_cell", 2876 | "valuable", 2877 | ] 2878 | 2879 | [[package]] 2880 | name = "tracing-log" 2881 | version = "0.1.3" 2882 | source = "registry+https://github.com/rust-lang/crates.io-index" 2883 | checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" 2884 | dependencies = [ 2885 | "lazy_static", 2886 | "log", 2887 | "tracing-core", 2888 | ] 2889 | 2890 | [[package]] 2891 | name = "tracing-subscriber" 2892 | version = "0.3.16" 2893 | source = "registry+https://github.com/rust-lang/crates.io-index" 2894 | checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" 2895 | dependencies = [ 2896 | "nu-ansi-term", 2897 | "sharded-slab", 2898 | "smallvec", 2899 | "thread_local", 2900 | "tracing-core", 2901 | "tracing-log", 2902 | ] 2903 | 2904 | [[package]] 2905 | name = "try-lock" 2906 | version = "0.2.3" 2907 | source = "registry+https://github.com/rust-lang/crates.io-index" 2908 | checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" 2909 | 2910 | [[package]] 2911 | name = "typenum" 2912 | version = "1.15.0" 2913 | source = "registry+https://github.com/rust-lang/crates.io-index" 2914 | checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" 2915 | 2916 | [[package]] 2917 | name = "unicase" 2918 | version = "2.6.0" 2919 | source = "registry+https://github.com/rust-lang/crates.io-index" 2920 | checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" 2921 | dependencies = [ 2922 | "version_check", 2923 | ] 2924 | 2925 | [[package]] 2926 | name = "unicode-bidi" 2927 | version = "0.3.8" 2928 | source = "registry+https://github.com/rust-lang/crates.io-index" 2929 | checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" 2930 | 2931 | [[package]] 2932 | name = "unicode-ident" 2933 | version = "1.0.5" 2934 | source = "registry+https://github.com/rust-lang/crates.io-index" 2935 | checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" 2936 | 2937 | [[package]] 2938 | name = "unicode-normalization" 2939 | version = "0.1.22" 2940 | source = "registry+https://github.com/rust-lang/crates.io-index" 2941 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 2942 | dependencies = [ 2943 | "tinyvec", 2944 | ] 2945 | 2946 | [[package]] 2947 | name = "unicode-width" 2948 | version = "0.1.10" 2949 | source = "registry+https://github.com/rust-lang/crates.io-index" 2950 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 2951 | 2952 | [[package]] 2953 | name = "unicode-xid" 2954 | version = "0.2.4" 2955 | source = "registry+https://github.com/rust-lang/crates.io-index" 2956 | checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" 2957 | 2958 | [[package]] 2959 | name = "universal-hash" 2960 | version = "0.4.1" 2961 | source = "registry+https://github.com/rust-lang/crates.io-index" 2962 | checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" 2963 | dependencies = [ 2964 | "generic-array", 2965 | "subtle", 2966 | ] 2967 | 2968 | [[package]] 2969 | name = "universal-hash" 2970 | version = "0.5.0" 2971 | source = "registry+https://github.com/rust-lang/crates.io-index" 2972 | checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" 2973 | dependencies = [ 2974 | "crypto-common", 2975 | "subtle", 2976 | ] 2977 | 2978 | [[package]] 2979 | name = "unsafe-libyaml" 2980 | version = "0.2.4" 2981 | source = "registry+https://github.com/rust-lang/crates.io-index" 2982 | checksum = "c1e5fa573d8ac5f1a856f8d7be41d390ee973daf97c806b2c1a465e4e1406e68" 2983 | 2984 | [[package]] 2985 | name = "untrusted" 2986 | version = "0.7.1" 2987 | source = "registry+https://github.com/rust-lang/crates.io-index" 2988 | checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" 2989 | 2990 | [[package]] 2991 | name = "url" 2992 | version = "2.3.1" 2993 | source = "registry+https://github.com/rust-lang/crates.io-index" 2994 | checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" 2995 | dependencies = [ 2996 | "form_urlencoded", 2997 | "idna", 2998 | "percent-encoding", 2999 | ] 3000 | 3001 | [[package]] 3002 | name = "utf-8" 3003 | version = "0.7.6" 3004 | source = "registry+https://github.com/rust-lang/crates.io-index" 3005 | checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" 3006 | 3007 | [[package]] 3008 | name = "utf8-width" 3009 | version = "0.1.6" 3010 | source = "registry+https://github.com/rust-lang/crates.io-index" 3011 | checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" 3012 | 3013 | [[package]] 3014 | name = "uuid" 3015 | version = "1.2.2" 3016 | source = "registry+https://github.com/rust-lang/crates.io-index" 3017 | checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c" 3018 | dependencies = [ 3019 | "getrandom 0.2.8", 3020 | ] 3021 | 3022 | [[package]] 3023 | name = "valuable" 3024 | version = "0.1.0" 3025 | source = "registry+https://github.com/rust-lang/crates.io-index" 3026 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 3027 | 3028 | [[package]] 3029 | name = "version_check" 3030 | version = "0.9.4" 3031 | source = "registry+https://github.com/rust-lang/crates.io-index" 3032 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 3033 | 3034 | [[package]] 3035 | name = "waker-fn" 3036 | version = "1.1.0" 3037 | source = "registry+https://github.com/rust-lang/crates.io-index" 3038 | checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" 3039 | 3040 | [[package]] 3041 | name = "want" 3042 | version = "0.3.0" 3043 | source = "registry+https://github.com/rust-lang/crates.io-index" 3044 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" 3045 | dependencies = [ 3046 | "log", 3047 | "try-lock", 3048 | ] 3049 | 3050 | [[package]] 3051 | name = "wasi" 3052 | version = "0.9.0+wasi-snapshot-preview1" 3053 | source = "registry+https://github.com/rust-lang/crates.io-index" 3054 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" 3055 | 3056 | [[package]] 3057 | name = "wasi" 3058 | version = "0.11.0+wasi-snapshot-preview1" 3059 | source = "registry+https://github.com/rust-lang/crates.io-index" 3060 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 3061 | 3062 | [[package]] 3063 | name = "wasm-bindgen" 3064 | version = "0.2.83" 3065 | source = "registry+https://github.com/rust-lang/crates.io-index" 3066 | checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" 3067 | dependencies = [ 3068 | "cfg-if", 3069 | "wasm-bindgen-macro", 3070 | ] 3071 | 3072 | [[package]] 3073 | name = "wasm-bindgen-backend" 3074 | version = "0.2.83" 3075 | source = "registry+https://github.com/rust-lang/crates.io-index" 3076 | checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" 3077 | dependencies = [ 3078 | "bumpalo", 3079 | "log", 3080 | "once_cell", 3081 | "proc-macro2", 3082 | "quote", 3083 | "syn", 3084 | "wasm-bindgen-shared", 3085 | ] 3086 | 3087 | [[package]] 3088 | name = "wasm-bindgen-futures" 3089 | version = "0.4.33" 3090 | source = "registry+https://github.com/rust-lang/crates.io-index" 3091 | checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" 3092 | dependencies = [ 3093 | "cfg-if", 3094 | "js-sys", 3095 | "wasm-bindgen", 3096 | "web-sys", 3097 | ] 3098 | 3099 | [[package]] 3100 | name = "wasm-bindgen-macro" 3101 | version = "0.2.83" 3102 | source = "registry+https://github.com/rust-lang/crates.io-index" 3103 | checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" 3104 | dependencies = [ 3105 | "quote", 3106 | "wasm-bindgen-macro-support", 3107 | ] 3108 | 3109 | [[package]] 3110 | name = "wasm-bindgen-macro-support" 3111 | version = "0.2.83" 3112 | source = "registry+https://github.com/rust-lang/crates.io-index" 3113 | checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" 3114 | dependencies = [ 3115 | "proc-macro2", 3116 | "quote", 3117 | "syn", 3118 | "wasm-bindgen-backend", 3119 | "wasm-bindgen-shared", 3120 | ] 3121 | 3122 | [[package]] 3123 | name = "wasm-bindgen-shared" 3124 | version = "0.2.83" 3125 | source = "registry+https://github.com/rust-lang/crates.io-index" 3126 | checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" 3127 | 3128 | [[package]] 3129 | name = "wasm-timer" 3130 | version = "0.2.5" 3131 | source = "registry+https://github.com/rust-lang/crates.io-index" 3132 | checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" 3133 | dependencies = [ 3134 | "futures", 3135 | "js-sys", 3136 | "parking_lot 0.11.2", 3137 | "pin-utils", 3138 | "wasm-bindgen", 3139 | "wasm-bindgen-futures", 3140 | "web-sys", 3141 | ] 3142 | 3143 | [[package]] 3144 | name = "web-sys" 3145 | version = "0.3.60" 3146 | source = "registry+https://github.com/rust-lang/crates.io-index" 3147 | checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" 3148 | dependencies = [ 3149 | "js-sys", 3150 | "wasm-bindgen", 3151 | ] 3152 | 3153 | [[package]] 3154 | name = "webpki" 3155 | version = "0.22.0" 3156 | source = "registry+https://github.com/rust-lang/crates.io-index" 3157 | checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" 3158 | dependencies = [ 3159 | "ring", 3160 | "untrusted", 3161 | ] 3162 | 3163 | [[package]] 3164 | name = "webpki-roots" 3165 | version = "0.22.5" 3166 | source = "registry+https://github.com/rust-lang/crates.io-index" 3167 | checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" 3168 | dependencies = [ 3169 | "webpki", 3170 | ] 3171 | 3172 | [[package]] 3173 | name = "wildmatch" 3174 | version = "2.1.1" 3175 | source = "registry+https://github.com/rust-lang/crates.io-index" 3176 | checksum = "ee583bdc5ff1cf9db20e9db5bb3ff4c3089a8f6b8b31aff265c9aba85812db86" 3177 | 3178 | [[package]] 3179 | name = "winapi" 3180 | version = "0.3.9" 3181 | source = "registry+https://github.com/rust-lang/crates.io-index" 3182 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 3183 | dependencies = [ 3184 | "winapi-i686-pc-windows-gnu", 3185 | "winapi-x86_64-pc-windows-gnu", 3186 | ] 3187 | 3188 | [[package]] 3189 | name = "winapi-i686-pc-windows-gnu" 3190 | version = "0.4.0" 3191 | source = "registry+https://github.com/rust-lang/crates.io-index" 3192 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 3193 | 3194 | [[package]] 3195 | name = "winapi-util" 3196 | version = "0.1.5" 3197 | source = "registry+https://github.com/rust-lang/crates.io-index" 3198 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 3199 | dependencies = [ 3200 | "winapi", 3201 | ] 3202 | 3203 | [[package]] 3204 | name = "winapi-x86_64-pc-windows-gnu" 3205 | version = "0.4.0" 3206 | source = "registry+https://github.com/rust-lang/crates.io-index" 3207 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 3208 | 3209 | [[package]] 3210 | name = "windows-sys" 3211 | version = "0.42.0" 3212 | source = "registry+https://github.com/rust-lang/crates.io-index" 3213 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 3214 | dependencies = [ 3215 | "windows_aarch64_gnullvm", 3216 | "windows_aarch64_msvc", 3217 | "windows_i686_gnu", 3218 | "windows_i686_msvc", 3219 | "windows_x86_64_gnu", 3220 | "windows_x86_64_gnullvm", 3221 | "windows_x86_64_msvc", 3222 | ] 3223 | 3224 | [[package]] 3225 | name = "windows_aarch64_gnullvm" 3226 | version = "0.42.0" 3227 | source = "registry+https://github.com/rust-lang/crates.io-index" 3228 | checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" 3229 | 3230 | [[package]] 3231 | name = "windows_aarch64_msvc" 3232 | version = "0.42.0" 3233 | source = "registry+https://github.com/rust-lang/crates.io-index" 3234 | checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" 3235 | 3236 | [[package]] 3237 | name = "windows_i686_gnu" 3238 | version = "0.42.0" 3239 | source = "registry+https://github.com/rust-lang/crates.io-index" 3240 | checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" 3241 | 3242 | [[package]] 3243 | name = "windows_i686_msvc" 3244 | version = "0.42.0" 3245 | source = "registry+https://github.com/rust-lang/crates.io-index" 3246 | checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" 3247 | 3248 | [[package]] 3249 | name = "windows_x86_64_gnu" 3250 | version = "0.42.0" 3251 | source = "registry+https://github.com/rust-lang/crates.io-index" 3252 | checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" 3253 | 3254 | [[package]] 3255 | name = "windows_x86_64_gnullvm" 3256 | version = "0.42.0" 3257 | source = "registry+https://github.com/rust-lang/crates.io-index" 3258 | checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" 3259 | 3260 | [[package]] 3261 | name = "windows_x86_64_msvc" 3262 | version = "0.42.0" 3263 | source = "registry+https://github.com/rust-lang/crates.io-index" 3264 | checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" 3265 | 3266 | [[package]] 3267 | name = "winreg" 3268 | version = "0.10.1" 3269 | source = "registry+https://github.com/rust-lang/crates.io-index" 3270 | checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" 3271 | dependencies = [ 3272 | "winapi", 3273 | ] 3274 | 3275 | [[package]] 3276 | name = "zeroize" 3277 | version = "1.3.0" 3278 | source = "registry+https://github.com/rust-lang/crates.io-index" 3279 | checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" 3280 | dependencies = [ 3281 | "zeroize_derive", 3282 | ] 3283 | 3284 | [[package]] 3285 | name = "zeroize_derive" 3286 | version = "1.3.3" 3287 | source = "registry+https://github.com/rust-lang/crates.io-index" 3288 | checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" 3289 | dependencies = [ 3290 | "proc-macro2", 3291 | "quote", 3292 | "syn", 3293 | "synstructure", 3294 | ] 3295 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "morum" 3 | version = "0.1.0" 4 | edition = "2021" 5 | authors = ["Wei Tang 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published by 637 | the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /base/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "morum-base" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | serde = { version = "1", features = ["derive"] } -------------------------------------------------------------------------------- /base/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod types; 2 | -------------------------------------------------------------------------------- /base/src/types.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] 4 | pub struct Category { 5 | pub title: String, 6 | pub topic: String, 7 | pub room_local_id: String, 8 | } 9 | 10 | #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] 11 | pub struct Post { 12 | pub title: String, 13 | pub topic: Option, 14 | pub room_id: String, 15 | } 16 | 17 | #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] 18 | pub struct Comment { 19 | pub html: String, 20 | pub sender: String, 21 | } 22 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | east_build_helper::build_trunk("ui"); 3 | } 4 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "locked": { 5 | "lastModified": 1659877975, 6 | "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", 7 | "owner": "numtide", 8 | "repo": "flake-utils", 9 | "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "numtide", 14 | "repo": "flake-utils", 15 | "type": "github" 16 | } 17 | }, 18 | "nixpkgs": { 19 | "locked": { 20 | "lastModified": 1669791787, 21 | "narHash": "sha256-KBfoA2fOI5+wCrm7PR+j7jHqXeTkVRPQ0m5fcKchyuU=", 22 | "owner": "nixos", 23 | "repo": "nixpkgs", 24 | "rev": "e76c78d20685a043d23f5f9e0ccd2203997f1fb1", 25 | "type": "github" 26 | }, 27 | "original": { 28 | "owner": "nixos", 29 | "ref": "nixos-unstable", 30 | "repo": "nixpkgs", 31 | "type": "github" 32 | } 33 | }, 34 | "root": { 35 | "inputs": { 36 | "nixpkgs": "nixpkgs", 37 | "rustOverlay": "rustOverlay" 38 | } 39 | }, 40 | "rustOverlay": { 41 | "inputs": { 42 | "flake-utils": "flake-utils", 43 | "nixpkgs": [ 44 | "nixpkgs" 45 | ] 46 | }, 47 | "locked": { 48 | "lastModified": 1669862269, 49 | "narHash": "sha256-/ar+cbAKAxd2Ng9b7EhrIMz9CP353RbmLecvyOidyUM=", 50 | "owner": "oxalica", 51 | "repo": "rust-overlay", 52 | "rev": "bfdf688742cf984c4837dbbe1c6cbca550365613", 53 | "type": "github" 54 | }, 55 | "original": { 56 | "owner": "oxalica", 57 | "repo": "rust-overlay", 58 | "type": "github" 59 | } 60 | } 61 | }, 62 | "root": "root", 63 | "version": 7 64 | } 65 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; 4 | rustOverlay.url = "github:oxalica/rust-overlay"; 5 | rustOverlay.inputs.nixpkgs.follows = "nixpkgs"; 6 | }; 7 | 8 | outputs = { self, nixpkgs, rustOverlay }: let 9 | pkgs = nixpkgs.legacyPackages."x86_64-linux"; 10 | rustPkgs = pkgs.extend rustOverlay.overlay; 11 | rustStable = rustPkgs.rustChannelOf { 12 | channel = "1.65.0"; 13 | }; 14 | rustWasm = rustStable.default.override { 15 | targets = [ "wasm32-unknown-unknown" ]; 16 | }; 17 | rustWasmPlatform = pkgs.makeRustPlatform { 18 | rustc = rustWasm; 19 | cargo = rustWasm; 20 | }; 21 | 22 | morumInputs = with pkgs; [ 23 | wasm-bindgen-cli binaryen clang pkg-config 24 | trunk nodePackages.sass 25 | ]; 26 | in { 27 | legacyPackages."x86_64-linux".morum = with pkgs; rustWasmPlatform.buildRustPackage rec { 28 | pname = "morum"; 29 | version = "0.1.0"; 30 | 31 | src = ./.; 32 | 33 | cargoSha256 = "sha256-zcODgyopUH/DJlD3km5o5GcE0R1HKZkbJLgBOVO9Bng="; 34 | nativeBuildInputs = morumInputs; 35 | }; 36 | 37 | devShell."x86_64-linux" = with pkgs; mkShell { 38 | buildInputs = morumInputs ++ [ rustWasm mold ]; 39 | }; 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /src/config.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] 4 | pub struct Config { 5 | pub homeserver_url: String, 6 | pub username: String, 7 | pub password: String, 8 | } 9 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | pub enum Error { 5 | #[error("Json Web Token related errors")] 6 | Jwt(#[from] jsonwebtoken::errors::Error), 7 | #[error("IO error")] 8 | Io(#[from] std::io::Error), 9 | #[error("Yaml parse error")] 10 | Yaml(#[from] serde_yaml::Error), 11 | #[error("Json parse error")] 12 | Json(#[from] serde_json::Error), 13 | // #[error("Appservice error")] 14 | // Appservice(#[from] matrix_sdk_appservice::Error), 15 | #[error("Url parsing error")] 16 | UrlParse(#[from] url::ParseError), 17 | #[error("Ruma client error")] 18 | RumaClient(Box), 19 | #[error("Matrix client build error")] 20 | MatrixClientBuild(#[from] matrix_sdk::ClientBuildError), 21 | #[error("Matrix error")] 22 | Matrix(#[from] matrix_sdk::Error), 23 | #[error("Matrix HTTP error")] 24 | MatrixHttp(#[from] matrix_sdk::HttpError), 25 | #[error("Matrix Id parsing error")] 26 | MatrixIdParse(#[from] ruma::IdParseError), 27 | #[error("System time error")] 28 | SystemTime(#[from] std::time::SystemTimeError), 29 | #[error("Hyper error")] 30 | Hyper(#[from] hyper::Error), 31 | #[error("Axum form error")] 32 | AxumForm(#[from] axum::extract::rejection::FormRejection), 33 | 34 | #[error("Already logged in")] 35 | AlreadyLoggedIn, 36 | #[error("Require logging in")] 37 | RequireLogin, 38 | #[error("Login credential is invalid")] 39 | InvalidLoginCredential, 40 | #[error("Unknown category")] 41 | UnknownCategory, 42 | #[error("Unknown post")] 43 | UnknownPost, 44 | #[error("Unknown post title")] 45 | UnknownPostTitle, 46 | #[error("Unknown category title")] 47 | UnknownCategoryTitle, 48 | #[error("Unknown category topic")] 49 | UnknownCategoryTopic, 50 | #[error("Unknown toplevel room")] 51 | UnknownToplevelRoom, 52 | #[error("Unknown category room")] 53 | UnknownCategoryRoom, 54 | #[error("Unknown category room")] 55 | InvalidCategoryAlias, 56 | } 57 | 58 | impl From for Error { 59 | fn from(err: std::convert::Infallible) -> Error { 60 | match err {} 61 | } 62 | } 63 | 64 | impl From> 65 | for Error 66 | { 67 | fn from(err: ruma::client::Error) -> Self { 68 | Self::RumaClient(Box::new(err)) 69 | } 70 | } 71 | 72 | impl From for std::io::Error { 73 | fn from(err: Error) -> std::io::Error { 74 | match dbg!(err) { 75 | Error::Io(err) => err, 76 | err => std::io::Error::new(std::io::ErrorKind::Other, err.to_string()), 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | mod error; 2 | 3 | pub mod config; 4 | pub mod matrix; 5 | pub mod web; 6 | 7 | pub use crate::config::Config; 8 | pub use crate::error::Error; 9 | pub use crate::matrix::MatrixService; 10 | pub use crate::web::UserError; 11 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use clap::Parser; 2 | use morum::{Config, Error}; 3 | use std::fs; 4 | 5 | #[derive(Parser, Debug)] 6 | struct Args { 7 | #[arg(short, long)] 8 | config: String, 9 | } 10 | 11 | async fn run() -> Result<(), Error> { 12 | let args = Args::parse(); 13 | tracing_subscriber::fmt::init(); 14 | 15 | let config: Config = serde_yaml::from_str(&fs::read_to_string(args.config)?)?; 16 | 17 | let matrix = morum::matrix::start(config.clone()).await?; 18 | 19 | morum::web::start(config, matrix).await?; 20 | 21 | Ok(()) 22 | } 23 | 24 | #[tokio::main] 25 | async fn main() -> Result<(), std::io::Error> { 26 | run().await?; 27 | Ok(()) 28 | } 29 | -------------------------------------------------------------------------------- /src/matrix.rs: -------------------------------------------------------------------------------- 1 | use crate::{Config, Error}; 2 | use matrix_sdk::Client; 3 | use matrix_sdk::{config::SyncSettings, room::MessagesOptions}; 4 | use morum_base::types; 5 | use regex::Regex; 6 | use ruma::events::{ 7 | room::name::RoomNameEventContent, room::topic::RoomTopicEventContent, EmptyStateKey, 8 | RedactContent, RedactedStateEventContent, StateEventContent, SyncStateEvent, 9 | }; 10 | use ruma::serde::Raw; 11 | use ruma::{assign, OwnedRoomId, RoomAliasId, RoomId, RoomOrAliasId}; 12 | use ruma_macros::EventContent; 13 | use serde::{Deserialize, Serialize}; 14 | use tokio::task; 15 | use tracing::info; 16 | use url::Url; 17 | 18 | fn deserialize_sync_state_events_to_content( 19 | events: Vec>>, 20 | ) -> Result, Error> 21 | where 22 | C: StateEventContent + RedactContent, 23 | C::Redacted: RedactedStateEventContent, 24 | { 25 | Ok(if let Some(event) = events.first() { 26 | let event = event.deserialize()?; 27 | 28 | if let SyncStateEvent::Original(event) = event { 29 | Some(event.content) 30 | } else { 31 | None 32 | } 33 | } else { 34 | None 35 | }) 36 | } 37 | 38 | #[derive(Clone, Debug, Deserialize, Serialize, EventContent)] 39 | #[ruma_event(type = "org.corepaper.morum.category", kind = State, state_key_type = EmptyStateKey)] 40 | pub struct MorumCategoryEventContent { 41 | #[serde(default, deserialize_with = "ruma::serde::empty_string_as_none")] 42 | pub category: Option, 43 | } 44 | 45 | #[derive(PartialEq, Eq, Clone, Debug)] 46 | pub struct Message { 47 | pub html: String, 48 | pub sender: String, 49 | } 50 | 51 | pub struct MatrixService { 52 | client: Client, 53 | } 54 | 55 | impl MatrixService { 56 | pub async fn new( 57 | homeserver_url: String, 58 | username: String, 59 | password: String, 60 | ) -> Result { 61 | let client = Client::new(Url::parse(&homeserver_url)?).await?; 62 | 63 | let login_res = client 64 | .login_username(&username, &password) 65 | .device_id("morum") 66 | .initial_device_display_name("Morum") 67 | .send() 68 | .await?; 69 | 70 | client 71 | .sync_once(SyncSettings::default().full_state(true)) 72 | .await?; 73 | 74 | let client_sync = client.clone(); 75 | task::spawn(async move { 76 | client_sync 77 | .sync(SyncSettings::default().full_state(true)) 78 | .await?; 79 | 80 | Ok::<(), matrix_sdk::Error>(()) 81 | }); 82 | 83 | info!( 84 | "Logged in as {}, got device_id {}", 85 | username, login_res.device_id, 86 | ); 87 | 88 | Ok(Self { client }) 89 | } 90 | 91 | pub async fn categories(&self) -> Result, Error> { 92 | use ruma::events::space::child::SpaceChildEventContent; 93 | 94 | let toplevel_room_id = self 95 | .client 96 | .resolve_room_alias("#forum:corepaper.org".try_into()?) 97 | .await? 98 | .room_id; 99 | let toplevel_room = self 100 | .client 101 | .get_joined_room(&toplevel_room_id) 102 | .ok_or(Error::UnknownToplevelRoom)?; 103 | 104 | let child_state_events = toplevel_room 105 | .get_state_events_static::() 106 | .await?; 107 | let children: Vec = child_state_events 108 | .into_iter() 109 | .filter_map(|event| { 110 | if let Ok(event) = event.deserialize() { 111 | Some(event.state_key().clone()) 112 | } else { 113 | None 114 | } 115 | }) 116 | .collect(); 117 | 118 | let mut categories = Vec::new(); 119 | for child in children { 120 | let room = self 121 | .client 122 | .get_joined_room(&child) 123 | .ok_or(Error::UnknownCategoryRoom)?; 124 | 125 | let room_name_state_events = room 126 | .get_state_events_static::() 127 | .await?; 128 | let room_topic_state_events = room 129 | .get_state_events_static::() 130 | .await?; 131 | 132 | let title = deserialize_sync_state_events_to_content(room_name_state_events)? 133 | .and_then(|e| e.name) 134 | .ok_or(Error::UnknownCategoryTitle)?; 135 | let topic = deserialize_sync_state_events_to_content(room_topic_state_events)? 136 | .map(|e| e.topic) 137 | .ok_or(Error::UnknownCategoryTopic)?; 138 | 139 | let room_alias = room.canonical_alias().ok_or(Error::InvalidCategoryAlias)?; 140 | let re = Regex::new(r"^#forum-(.+):corepaper\.org$").expect("regex is valid"); 141 | let captures = re.captures(room_alias.as_str()); 142 | 143 | let room_local_id = if let Some(captures) = captures { 144 | captures 145 | .get(1) 146 | .ok_or(Error::InvalidCategoryAlias)? 147 | .as_str() 148 | .to_owned() 149 | } else { 150 | return Err(Error::InvalidCategoryAlias); 151 | }; 152 | 153 | categories.push(types::Category { 154 | title, 155 | topic, 156 | room_local_id, 157 | }); 158 | } 159 | 160 | Ok(categories) 161 | } 162 | 163 | pub async fn category_posts( 164 | &self, 165 | room_alias: String, 166 | ) -> Result<(types::Category, Vec), Error> { 167 | use ruma::events::space::child::SpaceChildEventContent; 168 | 169 | let category_room_id = self 170 | .client 171 | .resolve_room_alias(&RoomAliasId::parse(&room_alias)?) 172 | .await? 173 | .room_id; 174 | let category_room = self 175 | .client 176 | .get_joined_room(&category_room_id) 177 | .ok_or(Error::UnknownCategoryRoom)?; 178 | 179 | let category_room_name_state_events = category_room 180 | .get_state_events_static::() 181 | .await?; 182 | let category_room_topic_state_events = category_room 183 | .get_state_events_static::() 184 | .await?; 185 | 186 | let category_title = 187 | deserialize_sync_state_events_to_content(category_room_name_state_events)? 188 | .and_then(|e| e.name) 189 | .ok_or(Error::UnknownCategoryTitle)?; 190 | let category_topic = 191 | deserialize_sync_state_events_to_content(category_room_topic_state_events)? 192 | .map(|e| e.topic) 193 | .ok_or(Error::UnknownCategoryTopic)?; 194 | 195 | let category_room_alias = category_room 196 | .canonical_alias() 197 | .ok_or(Error::InvalidCategoryAlias)?; 198 | let re = Regex::new(r"^#forum-(.+):corepaper\.org$").expect("regex is valid"); 199 | let captures = re.captures(category_room_alias.as_str()); 200 | 201 | let category_room_local_id = if let Some(captures) = captures { 202 | captures 203 | .get(1) 204 | .ok_or(Error::InvalidCategoryAlias)? 205 | .as_str() 206 | .to_owned() 207 | } else { 208 | return Err(Error::InvalidCategoryAlias); 209 | }; 210 | 211 | let category = types::Category { 212 | title: category_title, 213 | topic: category_topic, 214 | room_local_id: category_room_local_id, 215 | }; 216 | 217 | let child_state_events = category_room 218 | .get_state_events_static::() 219 | .await?; 220 | let children: Vec = child_state_events 221 | .into_iter() 222 | .filter_map(|event| { 223 | if let Ok(event) = event.deserialize() { 224 | Some(event.state_key().clone()) 225 | } else { 226 | None 227 | } 228 | }) 229 | .collect(); 230 | 231 | let mut posts = Vec::new(); 232 | for child in children { 233 | let room = self 234 | .client 235 | .get_joined_room(&child) 236 | .ok_or(Error::UnknownCategoryRoom)?; 237 | 238 | let room_name_state_events = room 239 | .get_state_events_static::() 240 | .await?; 241 | let room_topic_state_events = room 242 | .get_state_events_static::() 243 | .await?; 244 | 245 | let title = deserialize_sync_state_events_to_content(room_name_state_events)? 246 | .and_then(|e| e.name) 247 | .ok_or(Error::UnknownPostTitle)?; 248 | let topic = 249 | deserialize_sync_state_events_to_content(room_topic_state_events)?.map(|e| e.topic); 250 | 251 | let room_id = room.room_id(); 252 | 253 | posts.push(types::Post { 254 | title, 255 | topic, 256 | room_id: room_id.as_str().to_owned(), 257 | }); 258 | } 259 | 260 | Ok((category, posts)) 261 | } 262 | 263 | pub async fn post_comments( 264 | &self, 265 | room_id: String, 266 | ) -> Result<(types::Post, Vec), Error> { 267 | use ruma::events::room::message::{ 268 | sanitize::{HtmlSanitizerMode, RemoveReplyFallback}, 269 | FormattedBody, MessageFormat, MessageType, Relation, 270 | }; 271 | use ruma::events::{AnyMessageLikeEvent, AnyTimelineEvent, MessageLikeEvent}; 272 | 273 | let room = self 274 | .client 275 | .get_joined_room(&RoomId::parse(&room_id)?) 276 | .ok_or(Error::UnknownPost)?; 277 | 278 | let room_name_state_events = room 279 | .get_state_events_static::() 280 | .await?; 281 | let room_topic_state_events = room 282 | .get_state_events_static::() 283 | .await?; 284 | 285 | let title = deserialize_sync_state_events_to_content(room_name_state_events)? 286 | .and_then(|e| e.name) 287 | .ok_or(Error::UnknownPostTitle)?; 288 | let topic = 289 | deserialize_sync_state_events_to_content(room_topic_state_events)?.map(|e| e.topic); 290 | 291 | let post = types::Post { 292 | title, 293 | topic, 294 | room_id: room_id, 295 | }; 296 | 297 | let types_filter = ["m.room.message".to_string()]; 298 | let mut messages_options = MessagesOptions::backward(); 299 | messages_options.limit = js_int::UInt::MAX; 300 | messages_options.filter.types = Some(&types_filter); 301 | 302 | let messages_chunk = room.messages(messages_options).await?.chunk; 303 | 304 | let mut messages = Vec::new(); 305 | for message_raw in messages_chunk { 306 | let message = message_raw.event.deserialize()?; 307 | 308 | if let AnyTimelineEvent::MessageLike(AnyMessageLikeEvent::RoomMessage( 309 | MessageLikeEvent::Original(message), 310 | )) = message 311 | { 312 | let sender = message.sender; 313 | let (event_id, content) = match message.content.relates_to { 314 | Some(Relation::Replacement(replacement)) => ( 315 | replacement.event_id, 316 | replacement.new_content.as_ref().clone(), 317 | ), 318 | _ => (message.event_id, message.content), 319 | }; 320 | 321 | if let MessageType::Text(msgtype) = content.msgtype { 322 | if let Some((i, _)) = messages 323 | .iter() 324 | .enumerate() 325 | .find(|(_, (other_event_id, _, _))| *other_event_id == event_id) 326 | { 327 | let item = messages.remove(i); 328 | messages.push(item); 329 | } else { 330 | messages.push((event_id, sender, msgtype)); 331 | } 332 | } 333 | } 334 | } 335 | 336 | let mut comments = Vec::new(); 337 | for (_, sender, message) in messages { 338 | let mut message = message.formatted.unwrap_or_else(|| { 339 | let mut html_body = String::new(); 340 | 341 | pulldown_cmark::html::push_html( 342 | &mut html_body, 343 | pulldown_cmark::Parser::new(&message.body), 344 | ); 345 | FormattedBody::html(html_body) 346 | }); 347 | 348 | if message.format == MessageFormat::Html { 349 | message.sanitize_html(HtmlSanitizerMode::Strict, RemoveReplyFallback::Yes); 350 | let html = message.body; 351 | 352 | comments.push(types::Comment { 353 | sender: sender.as_str().to_owned(), 354 | html, 355 | }); 356 | } 357 | } 358 | 359 | comments.reverse(); 360 | 361 | Ok((post, comments)) 362 | } 363 | 364 | pub async fn add_room_to_space( 365 | &self, 366 | category_room_alias: String, 367 | new_room_alias_or_id: String, 368 | ) -> Result<(), Error> { 369 | use ruma::events::space::child::SpaceChildEventContent; 370 | 371 | let category_room_id = self 372 | .client 373 | .resolve_room_alias(&RoomAliasId::parse(&category_room_alias)?) 374 | .await? 375 | .room_id; 376 | let category_room = self 377 | .client 378 | .get_joined_room(&category_room_id) 379 | .ok_or(Error::UnknownCategoryRoom)?; 380 | 381 | let new_room_alias_or_id = RoomOrAliasId::parse(new_room_alias_or_id)?; 382 | let new_room_id = self 383 | .client 384 | .join_room_by_id_or_alias(&new_room_alias_or_id, &[]) 385 | .await? 386 | .room_id; 387 | 388 | category_room 389 | .send_state_event_for_key( 390 | &new_room_id, 391 | assign!(SpaceChildEventContent::new(), { 392 | via: Some(vec!["corepaper.org".try_into()?]), 393 | }), 394 | ) 395 | .await?; 396 | 397 | self.client 398 | .sync_once(SyncSettings::default().full_state(true)) 399 | .await?; 400 | 401 | Ok(()) 402 | } 403 | } 404 | 405 | pub async fn start(config: Config) -> Result { 406 | let matrix = 407 | MatrixService::new(config.homeserver_url, config.username, config.password).await?; 408 | 409 | matrix 410 | .post_comments("!AZvsRzlxPPMqKlMwMB:pacna.org".to_string()) 411 | .await?; 412 | 413 | Ok(matrix) 414 | } 415 | -------------------------------------------------------------------------------- /src/web/category_list.rs: -------------------------------------------------------------------------------- 1 | use super::{extract, AppState, Html}; 2 | use crate::Error; 3 | use east::{render, render_with_component}; 4 | use morum_ui::{AnyComponent, App, CategoryList}; 5 | 6 | pub async fn view_category_list(context: extract::State) -> Result { 7 | let categories = context.matrix.categories().await?; 8 | 9 | Ok(Html { 10 | header: render! { 11 | title { "Home | morum" }, 12 | }, 13 | body: render_with_component!(AnyComponent, { 14 | App { 15 | CategoryList { 16 | categories: categories, 17 | }, 18 | }, 19 | }), 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /src/web/extract.rs: -------------------------------------------------------------------------------- 1 | use crate::Error; 2 | use async_trait::async_trait; 3 | use axum::{body::HttpBody, extract::FromRequest, BoxError}; 4 | use http::Request; 5 | use serde::de::DeserializeOwned; 6 | use std::ops::Deref; 7 | 8 | pub use axum::extract::State; 9 | 10 | pub struct Form(pub T); 11 | 12 | #[async_trait] 13 | impl FromRequest for Form 14 | where 15 | T: DeserializeOwned, 16 | B: HttpBody + Send + 'static, 17 | B::Data: Send, 18 | B::Error: Into, 19 | S: Send + Sync, 20 | { 21 | type Rejection = Error; 22 | 23 | async fn from_request(req: Request, state: &S) -> Result { 24 | Ok(Form(axum::Form::from_request(req, state).await?.0)) 25 | } 26 | } 27 | 28 | impl Deref for Form { 29 | type Target = T; 30 | 31 | fn deref(&self) -> &Self::Target { 32 | &self.0 33 | } 34 | } 35 | 36 | pub use axum::extract::Path; 37 | -------------------------------------------------------------------------------- /src/web/mod.rs: -------------------------------------------------------------------------------- 1 | mod category_list; 2 | mod extract; 3 | mod post; 4 | mod post_list; 5 | mod user_error; 6 | 7 | pub use self::user_error::UserError; 8 | 9 | use crate::{Config, Error, MatrixService}; 10 | use axum::{middleware, routing, Router}; 11 | use std::{net::SocketAddr, ops::Deref, sync::Arc}; 12 | 13 | pub struct Context { 14 | pub config: Config, 15 | pub matrix: MatrixService, 16 | } 17 | 18 | #[derive(Clone)] 19 | pub struct AppState(Arc); 20 | 21 | impl Deref for AppState { 22 | type Target = Context; 23 | 24 | fn deref(&self) -> &Self::Target { 25 | &*self.0 26 | } 27 | } 28 | 29 | east_build::include_trunk_assets! { 30 | Asset = Asset, 31 | Html = Html, 32 | TRUNK_ASSET_FILES = TRUNK_ASSET_FILES, 33 | route_trunk_assets = route_trunk_assets, 34 | replace_header = "", 35 | replace_body = "", 36 | } 37 | 38 | pub async fn start(config: Config, matrix: MatrixService) -> Result<(), Error> { 39 | let context = Arc::new(Context { config, matrix }); 40 | 41 | let mut app: Router = Router::new(); 42 | 43 | app = route_trunk_assets(app); 44 | app = app 45 | .route("/", routing::get(self::category_list::view_category_list)) 46 | .route( 47 | "/category/:id", 48 | routing::get(self::post_list::view_post_list).post(self::post_list::act_post_list), 49 | ) 50 | .route("/post/:id", routing::get(self::post::view_post)); 51 | 52 | let state = AppState(context); 53 | 54 | let app: Router<()> = app 55 | .layer(middleware::from_fn_with_state( 56 | state.clone(), 57 | self::user_error::handle_error, 58 | )) 59 | .with_state(state); 60 | 61 | let addr = SocketAddr::from(([127, 0, 0, 1], 8080)); 62 | axum::Server::bind(&addr) 63 | .serve(app.into_make_service()) 64 | .await?; 65 | 66 | Ok(()) 67 | } 68 | -------------------------------------------------------------------------------- /src/web/post.rs: -------------------------------------------------------------------------------- 1 | use super::{extract, AppState, Html}; 2 | use crate::Error; 3 | use east::{render, render_with_component}; 4 | use morum_ui::{AnyComponent, App, Post}; 5 | 6 | pub async fn view_post( 7 | context: extract::State, 8 | path: extract::Path, 9 | ) -> Result { 10 | let room_id = path.0; 11 | 12 | let (post, comments) = context.matrix.post_comments(room_id).await?; 13 | 14 | Ok(Html { 15 | header: render! { 16 | title { format!("{} | morum", post.title) }, 17 | }, 18 | body: render_with_component!(AnyComponent, { 19 | App { 20 | Post { 21 | post: post, 22 | comments: comments, 23 | }, 24 | }, 25 | }), 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /src/web/post_list.rs: -------------------------------------------------------------------------------- 1 | use super::{extract, AppState, Html}; 2 | use crate::Error; 3 | use axum::response::Redirect; 4 | use east::{render, render_with_component}; 5 | use morum_ui::{AnyComponent, App, PostList}; 6 | use serde::Deserialize; 7 | 8 | pub async fn view_post_list( 9 | context: extract::State, 10 | path: extract::Path, 11 | ) -> Result { 12 | let room_local_id = path.0; 13 | 14 | let (category, posts) = context 15 | .matrix 16 | .category_posts(format!("#forum-{}:corepaper.org", room_local_id)) 17 | .await?; 18 | 19 | Ok(Html { 20 | header: render! { 21 | title { format!("{} | morum", category.title) }, 22 | }, 23 | body: render_with_component!(AnyComponent, { 24 | App { 25 | PostList { 26 | category: category, 27 | posts: posts, 28 | }, 29 | }, 30 | }), 31 | }) 32 | } 33 | 34 | #[derive(Deserialize)] 35 | #[serde(tag = "action")] 36 | pub enum PostListForm { 37 | NewPost { room_id: String }, 38 | } 39 | 40 | pub async fn act_post_list( 41 | context: extract::State, 42 | path: extract::Path, 43 | form: extract::Form, 44 | ) -> Result { 45 | let category_room_local_id = path.0; 46 | 47 | match form.0 { 48 | PostListForm::NewPost { room_id } => { 49 | context 50 | .matrix 51 | .add_room_to_space( 52 | format!("#forum-{}:corepaper.org", category_room_local_id), 53 | room_id, 54 | ) 55 | .await?; 56 | 57 | Ok(Redirect::to(&format!( 58 | "/category/{}", 59 | category_room_local_id 60 | ))) 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/web/user_error.rs: -------------------------------------------------------------------------------- 1 | use super::Html; 2 | use crate::Error; 3 | use axum::{ 4 | http::StatusCode, 5 | middleware::Next, 6 | response::{IntoResponse, Redirect, Response}, 7 | }; 8 | use east::{render, render_with_component}; 9 | use http::Request; 10 | use morum_ui::{AnyComponent, App}; 11 | use thiserror::Error; 12 | 13 | #[derive(Error, Debug)] 14 | pub enum UserError { 15 | #[error("Internal error")] 16 | Internal, 17 | } 18 | 19 | impl UserError { 20 | pub fn status_code(&self) -> Option { 21 | match self { 22 | Self::Internal => Some(StatusCode::INTERNAL_SERVER_ERROR), 23 | } 24 | } 25 | 26 | pub fn redirect(&self) -> Option { 27 | match self { 28 | _ => None, 29 | } 30 | } 31 | } 32 | 33 | impl From for UserError { 34 | fn from(err: Error) -> Self { 35 | match err { 36 | _ => Self::Internal, 37 | } 38 | } 39 | } 40 | 41 | impl IntoResponse for UserError { 42 | fn into_response(self) -> Response { 43 | let mut res = Response::new(Default::default()); 44 | res.extensions_mut().insert(self); 45 | res 46 | } 47 | } 48 | 49 | impl IntoResponse for Error { 50 | fn into_response(self) -> Response { 51 | let user_error = UserError::from(self); 52 | user_error.into_response() 53 | } 54 | } 55 | 56 | pub async fn handle_error(req: Request, next: Next) -> Response { 57 | let host = req.headers().get("Host"); 58 | let referer = req.headers().get("Referer"); 59 | let go_back = host 60 | .and_then(|host| host.to_str().ok()) 61 | .and_then(|host| referer.map(|referer| (host, referer))) 62 | .and_then(|(host, referer)| referer.to_str().ok().map(|referer| (host, referer))) 63 | .map(|(host, referer)| (host.to_string(), referer.to_string())) 64 | .and_then(|(host, referer)| { 65 | if referer.starts_with(&format!("https://{}", host)) 66 | || (referer.starts_with(&format!("http://{}", host)) 67 | && host.starts_with("127.0.0.1:")) 68 | { 69 | Some(referer) 70 | } else { 71 | None 72 | } 73 | }); 74 | 75 | let res = next.run(req).await; 76 | 77 | if let Some(error) = res.extensions().get::() { 78 | if let Some(redirect) = error.redirect() { 79 | return redirect.into_response(); 80 | } 81 | 82 | let html = Html { 83 | header: render! { 84 | title { "Error | morum" }, 85 | }, 86 | body: render_with_component!(AnyComponent, { 87 | App { 88 | p { 89 | class: "error", 90 | format!("{:?}", error), 91 | 92 | br { }, 93 | 94 | go_back.map(|go_back| { 95 | render! { 96 | a { 97 | class: "btn btn-primary", 98 | href: go_back.clone(), 99 | "Go back", 100 | } 101 | } 102 | }), 103 | }, 104 | }, 105 | }), 106 | }; 107 | 108 | if let Some(status_code) = error.status_code() { 109 | return (status_code, html).into_response(); 110 | } else { 111 | return html.into_response(); 112 | } 113 | } 114 | 115 | res 116 | } 117 | -------------------------------------------------------------------------------- /ui/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "morum-ui" 3 | version = "0.1.0" 4 | authors = ["Wei Tang 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /ui/src/category_list.rs: -------------------------------------------------------------------------------- 1 | use crate::AnyComponent; 2 | use east::{render_with_component, Markup, Render}; 3 | use morum_base::types; 4 | 5 | pub struct CategoryList { 6 | pub categories: Vec, 7 | } 8 | 9 | impl Render for CategoryList { 10 | fn render(self) -> Markup { 11 | render_with_component!(AnyComponent, { 12 | div { 13 | class: "row mb-1", 14 | h4 { 15 | "Categories", 16 | small { "All categories" }, 17 | } 18 | }, 19 | div { 20 | class: "row mb-3", 21 | self.categories.into_iter().map(|s| { 22 | CategoryListItem { category: s } 23 | }).collect::>() 24 | } 25 | }) 26 | } 27 | } 28 | 29 | pub struct CategoryListItem { 30 | pub category: types::Category, 31 | } 32 | 33 | impl Render for CategoryListItem { 34 | fn render(self) -> Markup { 35 | render_with_component!(AnyComponent, { 36 | div { 37 | class: "col-sm-6", 38 | div { 39 | class: "card", 40 | div { 41 | class: "card-body", 42 | h5 { 43 | class: "card-title", 44 | a { 45 | href: format!("/category/{}", self.category.room_local_id), 46 | self.category.title, 47 | } 48 | }, 49 | p { class: "card-text", self.category.topic }, 50 | }, 51 | }, 52 | } 53 | }) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ui/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod category_list; 2 | mod post; 3 | mod post_list; 4 | 5 | pub use crate::category_list::CategoryList; 6 | pub use crate::post::Post; 7 | pub use crate::post_list::PostList; 8 | 9 | use east::{render_from_multi, render_with_component, HydrateTo, Markup, Render, RenderMulti}; 10 | use serde::{Deserialize, Serialize}; 11 | 12 | #[derive(Serialize, Deserialize, HydrateTo, Debug, Clone)] 13 | pub enum AnyComponent {} 14 | 15 | pub struct App {} 16 | 17 | #[render_from_multi] 18 | impl RenderMulti for App { 19 | fn render_multi(self, children: Markup) -> Markup { 20 | render_with_component!(AnyComponent, { 21 | Nav { }, 22 | div { 23 | class: "container m-3", 24 | children, 25 | }, 26 | Footer { }, 27 | }) 28 | } 29 | } 30 | 31 | pub struct Nav {} 32 | 33 | impl Render for Nav { 34 | fn render(self) -> Markup { 35 | render_with_component!(AnyComponent, { 36 | nav { 37 | class: "navbar navbar-light navbar-expand-sm", 38 | span { 39 | class: "navbar-brand", 40 | a { href: "/", "morum" } 41 | }, 42 | ul { class: "navbar-bav" }, 43 | } 44 | }) 45 | } 46 | } 47 | 48 | pub struct Footer {} 49 | 50 | impl Render for Footer { 51 | fn render(self) -> Markup { 52 | render_with_component!(AnyComponent, { 53 | footer { 54 | class: "text-center text-lg-start text-muted mt-3", 55 | a { href: "https://that.world/legal.txt", target: "_blank", "Legal notice" }, ". ", 56 | "Copyright (c) 2022 Wei Tang. morum is licensed under ", 57 | a { href: "https://github.com/corepaper/morum", target: "_blank", "AGPL-3.0" }, ". ", 58 | } 59 | }) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /ui/src/main.rs: -------------------------------------------------------------------------------- 1 | use morum_ui::AnyComponent; 2 | 3 | fn main() { 4 | east::hydrate_all::(); 5 | } 6 | -------------------------------------------------------------------------------- /ui/src/post.rs: -------------------------------------------------------------------------------- 1 | use crate::AnyComponent; 2 | use east::{render, render_with_component, Markup, PreEscaped, Render}; 3 | use morum_base::types; 4 | 5 | pub struct Post { 6 | pub post: types::Post, 7 | pub comments: Vec, 8 | } 9 | 10 | impl Render for Post { 11 | fn render(self) -> Markup { 12 | render_with_component!(AnyComponent, { 13 | div { 14 | class: "row mb-3", 15 | h3 { 16 | self.post.title, 17 | br { }, 18 | self.post.topic.map(|t| { 19 | render! { small { t } } 20 | }) 21 | }, 22 | }, 23 | 24 | self.comments.into_iter().map(|comment| { 25 | render! { 26 | div { 27 | class: "row", 28 | div { 29 | class: "card", 30 | p { 31 | class: "card-text", 32 | strong { comment.sender } 33 | }, 34 | p { 35 | class: "card-text", 36 | PreEscaped(comment.html), 37 | } 38 | }, 39 | hr { } 40 | } 41 | } 42 | }).collect::>(), 43 | 44 | div { 45 | class: "row", 46 | a { 47 | "Post a new comment", 48 | class: "btn btn-primary", 49 | href: format!("https://matrix.to/#/{}", self.post.room_id), 50 | }, 51 | }, 52 | }) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ui/src/post_list.rs: -------------------------------------------------------------------------------- 1 | use crate::AnyComponent; 2 | use east::{render, render_with_component, Markup, Render}; 3 | use morum_base::types; 4 | 5 | pub struct PostList { 6 | pub category: types::Category, 7 | pub posts: Vec, 8 | } 9 | 10 | impl Render for PostList { 11 | fn render(self) -> Markup { 12 | render_with_component!(AnyComponent, { 13 | div { 14 | class: "row mb-3", 15 | h3 { 16 | self.category.title, 17 | small { self.category.topic }, 18 | }, 19 | }, 20 | 21 | self.posts.into_iter().map(|post| render! { 22 | div { 23 | class: "row", 24 | div { 25 | class: "card", 26 | h5 { 27 | class: "card-title", 28 | a { 29 | href: format!("/post/{}", post.room_id), 30 | post.title 31 | }, 32 | }, 33 | post.topic.map(|topic| render! { 34 | p { class: "card-text", topic } 35 | }), 36 | hr { }, 37 | }, 38 | }, 39 | }).collect::>(), 40 | 41 | div { 42 | class: "row", 43 | NewPost { }, 44 | }, 45 | }) 46 | } 47 | } 48 | 49 | pub struct NewPost {} 50 | 51 | impl Render for NewPost { 52 | fn render(self) -> Markup { 53 | render_with_component!(AnyComponent, { 54 | div { 55 | class: "col-12", 56 | form { 57 | method: "post", 58 | input { 59 | type_: "hidden", 60 | name: "action", 61 | value: "NewPost", 62 | }, 63 | div { 64 | class: "form-group", 65 | label { for_: "title", "Matrix Room ID" }, 66 | input { type_: "text", class: "form-control", id: "title", name: "room_id" }, 67 | }, 68 | input { 69 | class: "btn btn-primary pull-right", 70 | type_: "submit", 71 | value: "Add a new post", 72 | }, 73 | } 74 | } 75 | }) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /ui/styles/base.scss: -------------------------------------------------------------------------------- 1 | @import "contrast"; 2 | @import "bootstrap/scss/functions"; 3 | @import "bootstrap/scss/variables"; 4 | @import "variables"; 5 | @import "bootstrap/scss/mixins"; 6 | @import "bootstrap/scss/root"; 7 | @import "bootstrap/scss/reboot"; 8 | @import "bootstrap/scss/code"; 9 | @import "bootstrap/scss/type"; 10 | @import "bootstrap/scss/grid"; 11 | @import "bootstrap/scss/tables"; 12 | @import "bootstrap/scss/forms"; 13 | @import "bootstrap/scss/buttons"; 14 | @import "bootstrap/scss/transitions"; 15 | @import "bootstrap/scss/dropdown"; 16 | @import "bootstrap/scss/progress"; 17 | @import "bootstrap/scss/button-group"; 18 | @import "bootstrap/scss/input-group"; 19 | @import "bootstrap/scss/custom-forms"; 20 | @import "bootstrap/scss/nav"; 21 | @import "bootstrap/scss/navbar"; 22 | @import "bootstrap/scss/alert"; 23 | @import "bootstrap/scss/utilities"; 24 | @import "bootstrap/scss/print"; 25 | 26 | @import "icons"; 27 | @import "nav"; 28 | @import "events"; 29 | @import "highlight"; 30 | 31 | body { 32 | font-family: sans-serif; 33 | font-size: $base-font-size; 34 | padding-bottom: 1rem; 35 | text-align: initial; 36 | max-width: 47rem; 37 | } 38 | 39 | @include media-breakpoint-down(md) { 40 | .container { 41 | width: 100%; 42 | max-width: 100%; 43 | } 44 | } 45 | 46 | a { 47 | text-decoration: underline; 48 | 49 | &:hover { 50 | text-decoration: none; 51 | } 52 | } 53 | 54 | a.nav-link, a.navbar-brand, a.btn { 55 | text-decoration: none; 56 | } 57 | 58 | h1 a, h2 a, h3 a, h4 a, h5 a { 59 | text-decoration: none; 60 | 61 | &:hover { 62 | text-decoration: underline; 63 | } 64 | } 65 | 66 | label { 67 | margin-bottom: 0.25rem; 68 | } 69 | 70 | input[type="text"], 71 | input[type="email"], 72 | input[type="password"], 73 | input[type="tel"], 74 | textarea.form-control { 75 | border-radius: 0; 76 | border-color: #888; 77 | color: $gray-800; 78 | padding: 0.25rem 0.375rem; 79 | 80 | &:active, &:focus { 81 | color: $gray-800; 82 | } 83 | } 84 | 85 | input[type="checkbox"] { 86 | position: relative; 87 | top: 2px; 88 | } 89 | 90 | select:not([multiple]).form-control { 91 | border-radius: 0; 92 | border-color: #888; 93 | color: $gray-800; 94 | padding: 0 0.75rem; 95 | height: 1.9rem !important; 96 | } 97 | 98 | legend { 99 | font-size: $base-font-size; 100 | margin-bottom: 0; 101 | } 102 | 103 | h1, h2 { 104 | margin-top: 0; 105 | 106 | small { 107 | font-size: $base-font-size; 108 | } 109 | } 110 | 111 | h3 { 112 | font-size: 1.3rem; 113 | border-bottom: 1px solid $gray-200; 114 | padding-bottom: 0.25rem; 115 | 116 | small { 117 | font-size: 1rem; 118 | margin-left: 1rem; 119 | } 120 | } 121 | 122 | h4 { 123 | font-size: 1.1rem; 124 | border-bottom: 1px solid $gray-200; 125 | padding-bottom: 0.25rem; 126 | 127 | small { 128 | font-size: 0.8rem; 129 | margin-left: 1rem; 130 | } 131 | } 132 | 133 | h5 { 134 | font-size: 1rem; 135 | font-weight: bold; 136 | } 137 | 138 | .table { 139 | thead { 140 | th { 141 | padding: 0.1rem 0.75rem; 142 | border: none; 143 | } 144 | } 145 | 146 | tbody { 147 | td { 148 | position: relative; 149 | /* 150 | `position: relative` requires `background-clip: padding-box` to avoid the 151 | background being drawn on top of the borders on some OSes. Also, 152 | subsequently setting `background` will override `background-clip`, so make 153 | sure to use `background-color`. 154 | */ 155 | background-clip: padding-box; 156 | vertical-align: middle; 157 | padding: 0.1rem 0.75rem; 158 | border: 1px solid $gray-400; 159 | background-color: $white; 160 | 161 | label { 162 | margin-bottom: 0; 163 | } 164 | } 165 | } 166 | 167 | tr.danger { 168 | background: lighten($danger, 20); 169 | } 170 | 171 | .btn-danger.btn-fill { 172 | &:hover { 173 | background: $danger; 174 | } 175 | } 176 | } 177 | 178 | section { 179 | padding-bottom: 0.5rem; 180 | } 181 | 182 | @mixin btn_type($background, $foreground, $border, $hover) { 183 | /* FINDME */ 184 | background: $background; 185 | border: $border 1px solid; 186 | color: $foreground; 187 | 188 | @at-root a#{&} { 189 | color: $foreground; 190 | 191 | &:hover { 192 | color: color_adjust_contrast_AERT($foreground, $hover); 193 | } 194 | } 195 | 196 | &:hover { 197 | background: $hover; 198 | } 199 | } 200 | 201 | .btn { 202 | border-radius: 0; 203 | padding: 0.1rem 0.75rem; 204 | font-size: 0.9rem; 205 | transition: background 0.1s linear; 206 | } 207 | 208 | .btn-default { 209 | @include btn_type($gray-300, $black, $gray-800, $gray-200); 210 | } 211 | 212 | .btn-primary { 213 | @include btn_type(darken($primary, 10), $white, 214 | darken($primary, 40), $primary); 215 | } 216 | 217 | .btn-success { 218 | @include btn_type(darken($success, 12), 219 | color_adjust_contrast_AERT($white, darken($success, 5)), 220 | darken($success, 20), darken($success, 10)); 221 | } 222 | 223 | .btn-info { 224 | @include btn_type(darken($info, 10), $white, darken($info, 40), $info); 225 | } 226 | 227 | .btn-danger { 228 | @include btn_type(darken($danger, 5), $white, darken($danger, 40), $danger); 229 | } 230 | 231 | .btn.btn-link { 232 | padding: 0; 233 | font-size: $base-font-size; 234 | color: $black; 235 | margin-top: -0.1rem; 236 | text-decoration: underline; 237 | } 238 | 239 | .btn.btn-link:hover { 240 | text-decoration: none; 241 | } 242 | 243 | .btn-fill { 244 | display: block; 245 | position: absolute; 246 | left: 0; 247 | right: 0; 248 | top: 0; 249 | bottom: 0; 250 | width: 100%; 251 | border: none; 252 | padding: 0; 253 | line-height: 1.6; 254 | } 255 | 256 | .btn-sm { 257 | font-size: 0.95rem; 258 | padding: 0 0.75rem; 259 | } 260 | 261 | .alert { 262 | padding: 0.5rem; 263 | border-radius: 0; 264 | 265 | .form-group & { 266 | margin-top: 1rem; 267 | } 268 | } 269 | 270 | .text-centered { 271 | text-align: center; 272 | } 273 | 274 | .text-right { 275 | text-align: right; 276 | } 277 | 278 | .pull-left { 279 | float: left; 280 | } 281 | 282 | .pull-right { 283 | float: right; 284 | } 285 | 286 | blockquote { 287 | padding-left: 0.5rem; 288 | border-left: 3px solid #aaa; 289 | } 290 | 291 | pre { 292 | background: $pre-background; 293 | padding: 0.25rem; 294 | } 295 | 296 | code { 297 | margin: 0; 298 | background: transparent; 299 | color: black; 300 | } 301 | 302 | .markdown { 303 | table { 304 | @extend .table; 305 | } 306 | 307 | h1, h2, h3, h4, h5, h6 { 308 | position: relative; 309 | margin-top: 1em; 310 | 311 | &:first-child { 312 | margin-top: 0; 313 | } 314 | 315 | & > a:first-child { 316 | transition: opacity 0.15s linear; 317 | opacity: 0; 318 | position: absolute; 319 | font-size: inherit; 320 | left: -.7em; 321 | } 322 | 323 | @media(prefers-reduced-motion) { 324 | & > a:first-child { 325 | transition: none; 326 | } 327 | } 328 | 329 | &:hover > a:first-child { 330 | opacity: 1; 331 | } 332 | 333 | img { 334 | margin: 0 .2rem; 335 | max-width: 100%; 336 | } 337 | } 338 | } 339 | 340 | @media(prefers-color-scheme: dark) { 341 | @import "dark"; 342 | } 343 | -------------------------------------------------------------------------------- /ui/styles/contrast.scss: -------------------------------------------------------------------------------- 1 | /* 2 | SCSS Color Methods for Accessibility 3 | ================================================================================ 4 | Adjust given colors to ensure that those color combination provide sufficient 5 | contrast. 6 | @version 0.1 7 | @link http://eye48.com/go/scsscontrast 8 | @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License (LGPL) 9 | @author Michael Haschke, http://michael.haschke.biz/ 10 | Usage 11 | -------------------------------------------------------------------------------- 12 | Import contrast.scss first, then use method ``color_adjust_contrast_AERT``. 13 | ```(scss) 14 | @import 'libs/contrast'; 15 | .my-element { 16 | background-color: #eee; 17 | color: color_adjust_contrast_AERT(#ccc, #eee); // get grey with good contrast on #eee 18 | } 19 | ``` 20 | How it works 21 | -------------------------------------------------------------------------------- 22 | It tests for sufficent difference on brightness and color of two values. If it 23 | is not enough contrats regarding test formulas of accessible guidelines then one 24 | color is adjusted on lightness and saturation. 25 | Methods using calculations from: 26 | * "Techniques For Accessibility Evaluation And Repair Tools (AERT)" working draft, 27 | @see http://www.w3.org/TR/AERT#color-contrast 28 | * TODO: add methods to test with WCAG2 formulas 29 | */ 30 | 31 | // -- AERT ---------------------------------------------------------------- 32 | 33 | @function color_adjust_contrast_AERT( 34 | $color_adjust, 35 | $color_keep, 36 | $lightness_change_value:1, 37 | $saturation_change_value:1, 38 | $brightness_min: 50, 39 | $difference_min: 450) 40 | { 41 | 42 | @if (color_test_contrast_AERT($color_adjust, $color_keep, $brightness_min, $difference_min) == true) 43 | { 44 | @return $color_adjust; 45 | } 46 | 47 | $color_save: $color_adjust; 48 | $S: saturation($color_adjust); 49 | $L: lightness($color_adjust); 50 | 51 | $foundresult: false; 52 | @while(($foundresult == false) and ($S > 0 or ($L > 0 and $L < 100))) 53 | { 54 | $color_adjust: desaturate($color_adjust, $saturation_change_value); 55 | 56 | $S: $S - $saturation_change_value; 57 | @if (lightness($color_keep) > lightness($color_adjust)) 58 | { 59 | $color_adjust: darken($color_adjust, $lightness_change_value); 60 | $L: $L - $lightness_change_value; 61 | } 62 | @else 63 | { 64 | $color_adjust: lighten($color_adjust, $lightness_change_value); 65 | $L: $L + $lightness_change_value; 66 | } 67 | $foundresult: color_test_contrast_AERT($color_adjust, $color_keep, $brightness_min, $difference_min); 68 | } 69 | 70 | @if ($foundresult == false) 71 | { 72 | @debug $color_save + " was adjusted to " + $color_adjust + " but this is not enough contrast to " + $color_keep + " (AERT)."; 73 | } 74 | 75 | @return $color_adjust; 76 | } 77 | 78 | @function color_test_contrast_AERT($color_1, $color_2, $brightness_min: 75, $difference_min: 500) 79 | { 80 | $difference_brightness: math_absolute(color_brightness_AERT($color_1) - color_brightness_AERT($color_2)); 81 | $difference_color: color_difference_AERT($color_1, $color_2); 82 | 83 | @if (($difference_brightness < $brightness_min) or ($difference_color < $difference_min)) 84 | { 85 | @return false; 86 | } 87 | @else 88 | { 89 | @return true; 90 | } 91 | } 92 | 93 | @function color_brightness_AERT($color) 94 | { 95 | $r: red($color); 96 | $g: green($color); 97 | $b: blue($color); 98 | 99 | @return calc((($r * 299) + ($g * 587) + ($b * 114)) / 1000); 100 | } 101 | 102 | @function color_difference_AERT($color1, $color2) 103 | { 104 | $r1: red($color1); 105 | $g1: green($color1); 106 | $b1: blue($color1); 107 | 108 | $r2: red($color2); 109 | $g2: green($color2); 110 | $b2: blue($color2); 111 | 112 | @return (math_max($r1, $r2) - math_min($r1, $r2)) + (math_max($g1, $g2) - math_min($g1, $g2)) + (math_max($b1, $b2) - math_min($b1, $b2)); 113 | } 114 | 115 | // -- math stuff ---------------------------------------------------------- 116 | 117 | @function math_max($value1, $value2) 118 | { 119 | @if ($value1 > $value2) { @return $value1; } 120 | @return $value2; 121 | } 122 | 123 | @function math_min($value1, $value2) 124 | { 125 | @if ($value1 < $value2) { @return $value1; } 126 | @return $value2; 127 | } 128 | 129 | @function math_absolute($value) 130 | { 131 | @if ($value > 0) { @return $value; } 132 | @return $value * -1; 133 | } 134 | -------------------------------------------------------------------------------- /ui/styles/dark.scss: -------------------------------------------------------------------------------- 1 | $primary-dark: darken($primary, 10); 2 | $success-dark: #2bb34b; 3 | $danger-dark: #ff3e3e; 4 | $muted-dark: $gray-400; 5 | $link-dark: lighten($primary, 10); 6 | $darker: darken($gray-900, 6); 7 | $border: $gray-700; 8 | 9 | body { 10 | background: $gray-900; 11 | color: $gray-100; 12 | } 13 | 14 | .event { 15 | background: $darker; 16 | color: $white; 17 | 18 | a:not(.btn) { 19 | color: $link-dark; 20 | } 21 | } 22 | 23 | a { 24 | color: $link-dark; 25 | } 26 | 27 | h3, h4 { 28 | border-bottom-color: $gray-700; 29 | } 30 | 31 | pre { 32 | color: $white; 33 | background: $darker; 34 | } 35 | 36 | code { 37 | color: $white; 38 | } 39 | 40 | .text-success { 41 | // Whose brilliant idea was it to make the text- classes !important in 42 | // bootstrap? 43 | color: $success-dark !important; 44 | } 45 | 46 | .text-danger { 47 | color: $danger-dark !important; 48 | } 49 | 50 | .text-muted { 51 | color: $muted-dark !important; 52 | } 53 | 54 | .alert-info { 55 | background-color: darken(#d1ecf1, 20); 56 | border-color: darken(#bee5eb, 10); 57 | color: black; 58 | 59 | a:not(.btn) { 60 | color: darken($primary, 20); 61 | } 62 | } 63 | 64 | .alert-success { 65 | background-color: darken(#d4edda, 20); 66 | border-color: darken(#c3e6cb, 10); 67 | color: $black; 68 | } 69 | 70 | .alert-danger { 71 | background-color: darken(#f8d7da, 12); 72 | border-color: darken(#f5c6cb, 10); 73 | color: $black; 74 | 75 | a:not(.btn) { 76 | color: darken($primary, 15); 77 | } 78 | } 79 | 80 | .alert-warning { 81 | background-color: darken(#fff3cd, 8); 82 | border-color: darken(#ffeeba, 10); 83 | color: $black; 84 | 85 | a:not(.btn) { 86 | color: darken($primary, 15); 87 | } 88 | } 89 | 90 | input[type="text"], 91 | input[type="password"], 92 | input[type="email"], 93 | input[type="email"].form-control, 94 | textarea, 95 | textarea.form-control, 96 | select.form-control:not([multiple]), 97 | .form-control { 98 | background: $darker; 99 | color: $white; 100 | border-color: $border; 101 | 102 | &:active, &:focus { 103 | background: $gray-900; 104 | color: $white; 105 | } 106 | 107 | &[disabled], &[readonly] { 108 | background: $gray-900; 109 | color: $gray-400; 110 | } 111 | } 112 | 113 | .btn { 114 | &.btn-default { 115 | background: $gray-900; 116 | color: $white; 117 | border-color: $border; 118 | 119 | &:hover { 120 | background: $darker; 121 | color: $white; 122 | } 123 | } 124 | 125 | &.btn-link { 126 | color: $link-dark; 127 | } 128 | 129 | &.btn-primary, 130 | &.btn-success, 131 | &.btn-danger { 132 | border-color: $darker; 133 | } 134 | } 135 | 136 | .table, 137 | .table tbody tr, 138 | .table tbody td, 139 | .table thead th { 140 | background: $gray-800; 141 | } 142 | 143 | .table tbody td { 144 | border: 1px solid $gray-900; 145 | } 146 | 147 | .navbar-light { 148 | .navbar-brand, 149 | .navbar-brand a, 150 | .navbar-text, 151 | .navbar-text a, 152 | .navbar-text a:hover, 153 | .navbar-text a:focus, 154 | .navbar-brand a:hover, 155 | .navbar-brand:hover { 156 | color: $white; 157 | } 158 | 159 | .navbar-nav { 160 | .nav-link { 161 | // gray-600 is too dark and gray-500 is too light 162 | color: lighten($gray-600, 5); 163 | 164 | &:focus { 165 | color: $gray-500; 166 | } 167 | 168 | &:hover { 169 | color: $white; 170 | } 171 | } 172 | 173 | .active .nav-link { 174 | color: $white; 175 | } 176 | } 177 | } 178 | 179 | $headerbg: $darker; 180 | 181 | .header-extension { 182 | background: $headerbg; 183 | } 184 | 185 | .header-tabbed { 186 | border-color: $headerbg; 187 | 188 | .nav { 189 | .nav-item .nav-link.active, 190 | .nav-item .nav-link:hover { 191 | color: $white; 192 | background: $headerbg; 193 | border-color: $headerbg; 194 | } 195 | 196 | .nav-link { 197 | color: $gray-400; 198 | } 199 | } 200 | } 201 | 202 | @import "highlight-dark"; 203 | -------------------------------------------------------------------------------- /ui/styles/events.scss: -------------------------------------------------------------------------------- 1 | .event-list { 2 | margin-bottom: 1rem; 3 | } 4 | 5 | .event { 6 | text-overflow: ellipsis; 7 | overflow: hidden; 8 | padding: 0.5rem; 9 | margin: 0.5rem 0; 10 | background: $event-background; 11 | @include anchor_with_contrast($background: $event-background); 12 | 13 | .text-muted { 14 | color: color_adjust_contrast_AERT($text-muted, $event-background); 15 | } 16 | 17 | &:first-child { 18 | margin-top: 0; 19 | } 20 | 21 | &:last-child { 22 | margin-bottom: 0; 23 | } 24 | 25 | h4 { 26 | text-overflow: ellipsis; 27 | white-space: nowrap; 28 | overflow: hidden; 29 | margin-bottom: 0; 30 | padding: 0; 31 | } 32 | 33 | blockquote { 34 | margin-bottom: 0.5rem; 35 | 36 | *:last-child { 37 | margin-bottom: 0; 38 | } 39 | } 40 | 41 | *:last-child { 42 | margin-bottom: 0; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ui/styles/highlight-dark.scss: -------------------------------------------------------------------------------- 1 | .highlight { background: #272822; color: #f8f8f2 !important } 2 | .highlight .bp { color: #f8f8f2 !important } /* Name.Builtin.Pseudo */ 3 | .highlight .c { color: #a6a087 !important } /* Comment */ 4 | .highlight .c1 { color: #a6a087 !important } /* Comment.Single */ 5 | .highlight .ch { color: #a6a087 !important } /* Comment.Hashbang */ 6 | .highlight .cm { color: #a6a087 !important } /* Comment.Multiline */ 7 | .highlight .cp { color: #a6a087 !important } /* Comment.Preproc */ 8 | .highlight .cpf { color: #a6a087 !important} /* Comment.PreprocFile */ 9 | .highlight .cs { color: #a6a087 !important } /* Comment.Special */ 10 | .highlight .dl { color: #e6db74 !important } /* Literal.String.Delimiter */ 11 | .highlight .err { color: #960050; background-color: #1e0010 !important } /* Error */ 12 | .highlight .fm { color: #3299ff !important } /* Name.Function.Magic */ 13 | .highlight .gd { color: #f92672 !important } /* Generic.Deleted */ 14 | .highlight .ge { font-style: italic !important } /* Generic.Emph */ 15 | .highlight .gh { color: #619fef !important } /* Generic.Heading */ 16 | .highlight .gi { color: #00A000 !important} /* Generic.Inserted */ 17 | .highlight .go { color: #888888 !important} /* Generic.Output */ 18 | .highlight .gp { color: #619fef !important } /* Generic.Prompt */ 19 | .highlight .gr { color: #960050 !important } /* Generic.Error */ 20 | .highlight .gs { font-weight: bold !important } /* Generic.Strong */ 21 | .highlight .gt { color: #0044DD !important } /* Generic.Traceback */ 22 | .highlight .gu { color: #ae81ff !important } /* Generic.Subheading */ 23 | .highlight .hll { background-color: #49483e !important } /* Highlighted Line */ 24 | .highlight .il { color: #ae81ff !important } /* Literal.Number.Integer.Long */ 25 | .highlight .k { color: #66d9ef !important } /* Keyword */ 26 | .highlight .kc { color: #66d9ef !important } /* Keyword.Constant */ 27 | .highlight .kd { color: #66d9ef !important } /* Keyword.Declaration */ 28 | .highlight .kn { color: #f92672 !important } /* Keyword.Namespace */ 29 | .highlight .kp { color: #66d9ef !important } /* Keyword.Pseudo */ 30 | .highlight .kr { color: #66d9ef !important } /* Keyword.Reserved */ 31 | .highlight .kt { color: #66d9ef !important } /* Keyword.Type */ 32 | .highlight .l { color: #ae81ff !important } /* Literal */ 33 | .highlight .ld { color: #e6db74 !important } /* Literal.Date */ 34 | .highlight .m { color: #ae81ff !important } /* Literal.Number */ 35 | .highlight .mb { color: #ae81ff !important } /* Literal.Number.Bin */ 36 | .highlight .mf { color: #ae81ff !important } /* Literal.Number.Float */ 37 | .highlight .mh { color: #ae81ff !important } /* Literal.Number.Hex */ 38 | .highlight .mi { color: #ae81ff !important } /* Literal.Number.Integer */ 39 | .highlight .mo { color: #ae81ff !important } /* Literal.Number.Oct */ 40 | .highlight .n { color: inherit } /* Name */ 41 | .highlight .na { color: #a6e22e !important } /* Name.Attribute */ 42 | .highlight .nb { color: #f8f8f2 !important } /* Name.Builtin */ 43 | .highlight .nc { color: #a6e22e !important } /* Name.Class */ 44 | .highlight .nd { color: #a6e22e !important } /* Name.Decorator */ 45 | .highlight .ne { color: #a6e22e !important } /* Name.Exception */ 46 | .highlight .nf { color: #a6e22e !important } /* Name.Function */ 47 | .highlight .ni { color: #f8f8f2 !important } /* Name.Entity */ 48 | .highlight .nl { color: #f8f8f2 !important } /* Name.Label */ 49 | .highlight .nn { color: #f8f8f2 !important } /* Name.Namespace */ 50 | .highlight .no { color: #66d9ef !important } /* Name.Constant */ 51 | .highlight .nt { color: #f92672 !important } /* Name.Tag */ 52 | .highlight .nv { color: #f8f8f2 !important } /* Name.Variable */ 53 | .highlight .nx { color: #fefefe !important } /* Name.Other */ 54 | .highlight .o { color: #f92672 !important } /* Operator */ 55 | .highlight .ow { color: #f92672 !important } /* Operator.Word */ 56 | .highlight .p { color: #f8f8f2 !important } /* Punctuation */ 57 | .highlight .py { color: #f8f8f2 !important } /* Name.Property */ 58 | .highlight .s { color: #e6db74 !important } /* Literal.String */ 59 | .highlight .s1 { color: #e6db74 !important } /* Literal.String.Single */ 60 | .highlight .s2 { color: #e6db74 !important } /* Literal.String.Double */ 61 | .highlight .sa { color: #e6db74 !important } /* Literal.String.Affix */ 62 | .highlight .sb { color: #e6db74 !important } /* Literal.String.Backtick */ 63 | .highlight .sc { color: #e6db74 !important } /* Literal.String.Char */ 64 | .highlight .sd { color: #e6db74 !important } /* Literal.String.Doc */ 65 | .highlight .se { color: #ae81ff !important } /* Literal.String.Escape */ 66 | .highlight .sh { color: #e6db74 !important } /* Literal.String.Heredoc */ 67 | .highlight .si { color: #e6db74 !important } /* Literal.String.Interpol */ 68 | .highlight .sr { color: #e6db74 !important } /* Literal.String.Regex */ 69 | .highlight .ss { color: #e6db74 !important } /* Literal.String.Symbol */ 70 | .highlight .sx { color: #e6db74 !important } /* Literal.String.Other */ 71 | .highlight .vc { color: #f8f8f2 !important } /* Name.Variable.Class */ 72 | .highlight .vg { color: #f8f8f2 !important } /* Name.Variable.Global */ 73 | .highlight .vi { color: #f8f8f2 !important } /* Name.Variable.Instance */ 74 | .highlight .vm { color: #f8f8f2 !important } /* Name.Variable.Magic */ 75 | .highlight .w { color: #f8f8f2 !important } /* Text.Whitespace */ 76 | -------------------------------------------------------------------------------- /ui/styles/highlight.scss: -------------------------------------------------------------------------------- 1 | .highlight { background: #f8f8f8; } 2 | .highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ 3 | .highlight .c { color: #408080; font-style: italic } /* Comment */ 4 | .highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */ 5 | .highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */ 6 | .highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */ 7 | .highlight .cp { color: darken(#BC7A00, 5); } /* Comment.Preproc */ 8 | .highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */ 9 | .highlight .cs { color: #408080; font-style: italic } /* Comment.Special */ 10 | .highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */ 11 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 12 | .highlight .fm { color: #0000FF } /* Name.Function.Magic */ 13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 14 | .highlight .ge { font-style: italic } /* Generic.Emph */ 15 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 16 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 17 | .highlight .go { color: #212529 } /* Generic.Output */ 18 | .highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ 19 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 20 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 21 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 22 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 23 | .highlight .hll { background-color: #ffffcc } /* Highlighted Line */ 24 | .highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ 25 | .highlight .k { color: #008000; font-weight: bold } /* Keyword */ 26 | .highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ 27 | .highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ 28 | .highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ 29 | .highlight .kp { color: #008000 } /* Keyword.Pseudo */ 30 | .highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ 31 | .highlight .kt { color: #B00040 } /* Keyword.Type */ 32 | .highlight .l { color: #800080 } /* Literal */ 33 | .highlight .ld { color: #BA2121 } /* Literal.Date */ 34 | .highlight .m { color: #666666 } /* Literal.Number */ 35 | .highlight .mb { color: #666666 } /* Literal.Number.Bin */ 36 | .highlight .mf { color: #666666 } /* Literal.Number.Float */ 37 | .highlight .mh { color: #666666 } /* Literal.Number.Hex */ 38 | .highlight .mi { color: #666666 } /* Literal.Number.Integer */ 39 | .highlight .mo { color: #666666 } /* Literal.Number.Oct */ 40 | .highlight .n { color: inherit } /* Name */ 41 | .highlight .na { color: #7D9029 } /* Name.Attribute */ 42 | .highlight .nb { color: #008000 } /* Name.Builtin */ 43 | .highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ 44 | .highlight .nd { color: #AA22FF } /* Name.Decorator */ 45 | .highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ 46 | .highlight .nf { color: #0000FF } /* Name.Function */ 47 | .highlight .ni { color: #212529; font-weight: bold } /* Name.Entity */ 48 | .highlight .nl { color: darken(#A0A000, 10); } /* Name.Label */ 49 | .highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ 50 | .highlight .no { color: #880000 } /* Name.Constant */ 51 | .highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ 52 | .highlight .nv { color: #19177C } /* Name.Variable */ 53 | .highlight .nx { color: #19177C } /* Name.Other */ 54 | .highlight .o { color: #666666 } /* Operator */ 55 | .highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ 56 | .highlight .p { color: #19177C } /* Punctuation */ 57 | .highlight .py { color: #19177C } /* Name.Property */ 58 | .highlight .s { color: #BA2121 } /* Literal.String */ 59 | .highlight .s1 { color: #BA2121 } /* Literal.String.Single */ 60 | .highlight .s2 { color: #BA2121 } /* Literal.String.Double */ 61 | .highlight .sa { color: #BA2121 } /* Literal.String.Affix */ 62 | .highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ 63 | .highlight .sc { color: #BA2121 } /* Literal.String.Char */ 64 | .highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ 65 | .highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ 66 | .highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ 67 | .highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ 68 | .highlight .sr { color: #BB6688 } /* Literal.String.Regex */ 69 | .highlight .ss { color: #19177C } /* Literal.String.Symbol */ 70 | .highlight .sx { color: #008000 } /* Literal.String.Other */ 71 | .highlight .vc { color: #19177C } /* Name.Variable.Class */ 72 | .highlight .vg { color: #19177C } /* Name.Variable.Global */ 73 | .highlight .vi { color: #19177C } /* Name.Variable.Instance */ 74 | .highlight .vm { color: #19177C } /* Name.Variable.Magic */ 75 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 76 | -------------------------------------------------------------------------------- /ui/styles/icons.scss: -------------------------------------------------------------------------------- 1 | .icon { 2 | display: inline-block; 3 | line-height: .75em; 4 | 5 | svg { 6 | display: block; 7 | } 8 | 9 | path { 10 | fill: currentColor; 11 | } 12 | 13 | width: 1.1em; 14 | vertical-align: -0.2em; 15 | 16 | .btn & { 17 | vertical-align: -0.3em; 18 | } 19 | 20 | &.sm { 21 | width: 0.9em; 22 | vertical-align: -0.2em; 23 | } 24 | } 25 | 26 | @keyframes fa-spin { 27 | 0% { 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | transform: rotate(1turn); 32 | } 33 | } 34 | 35 | .icon-spin { 36 | animation: fa-spin 2s infinite linear; 37 | } 38 | 39 | .icon-caret-left, 40 | .icon-caret-right { 41 | width: 0.5em; 42 | vertical-align: -0.35em; 43 | 44 | &.sm { 45 | width: 0.4em; 46 | } 47 | 48 | .btn & { 49 | margin-left: 0.2rem; 50 | } 51 | } 52 | 53 | .icon-times { 54 | width: 0.8em; 55 | vertical-align: -0.25em; 56 | } 57 | -------------------------------------------------------------------------------- /ui/styles/nav.scss: -------------------------------------------------------------------------------- 1 | .navbar { 2 | flex-wrap: wrap; 3 | 4 | .navbar-nav { 5 | flex-grow: 1; 6 | flex-wrap: nowrap; 7 | 8 | @include media-breakpoint-down(xs) { 9 | flex-direction: row !important; 10 | 11 | .nav-link { 12 | padding: 0 0.5rem; 13 | 14 | &:first-child { 15 | padding-left: 0; 16 | } 17 | } 18 | } 19 | } 20 | 21 | .nav-link:hover { 22 | text-decoration: underline; 23 | } 24 | 25 | .navbar-text { 26 | color: $black; 27 | 28 | @include media-breakpoint-down(md) { 29 | padding: 0; 30 | } 31 | } 32 | } 33 | 34 | .navbar-light .navbar-brand { 35 | a { 36 | text-decoration: none; 37 | color: $black; 38 | 39 | &:hover { 40 | text-decoration: underline; 41 | } 42 | } 43 | 44 | .icon { 45 | position: relative; 46 | top: 1px; 47 | } 48 | } 49 | 50 | .nav-tabs { 51 | padding-left: 1rem; 52 | margin-bottom: 0.5rem; 53 | border-bottom: 3px $nav-tabs-background solid; 54 | 55 | .nav-link { 56 | padding: 0 1rem; 57 | border-radius: 0; 58 | border: none; 59 | color: color_adjust_contrast_AERT($gray-600, white); 60 | cursor: pointer; 61 | 62 | &.active, &.active:hover { 63 | color: black; 64 | background: $nav-tabs-background; 65 | } 66 | 67 | &[disabled], &[disabled]:hover { 68 | color: $gray-800; 69 | cursor: not-allowed; 70 | background: transparent; 71 | } 72 | } 73 | } 74 | 75 | .header-tabbed { 76 | border-bottom: 3px solid $nav-tabs-background; 77 | margin-bottom: 1rem; 78 | 79 | .container, .container-fluid { 80 | display: flex; 81 | flex-wrap: wrap; 82 | 83 | @include media-breakpoint-down(sm) { 84 | flex-direction: column; 85 | } 86 | } 87 | 88 | &.vertical { 89 | align-items: inherit; 90 | flex-direction: column; 91 | } 92 | 93 | h2 { 94 | display: inline; 95 | margin: 0; 96 | padding-right: 1rem; 97 | } 98 | 99 | .nav { 100 | border: none; 101 | margin: 0; 102 | flex-grow: 1; 103 | display: inline-flex; 104 | flex-wrap: nowrap; 105 | padding: 0; 106 | 107 | li { 108 | align-self: flex-end; 109 | } 110 | 111 | .nav-item:hover { 112 | background: $nav-tabs-background; 113 | a { 114 | color: black; 115 | } 116 | } 117 | 118 | .nav-text { 119 | padding: 0 1rem; 120 | margin-right: 1rem; 121 | 122 | &.vis-private { 123 | border-bottom: 3px solid $danger; 124 | margin-bottom: -3px; 125 | } 126 | 127 | &.vis-unlisted { 128 | border-bottom: 3px solid $info; 129 | margin-bottom: -3px; 130 | } 131 | 132 | &:hover { 133 | background: transparent; 134 | } 135 | 136 | @include media-breakpoint-down(sm) { 137 | display: none; 138 | } 139 | } 140 | 141 | @include media-breakpoint-down(sm) { 142 | flex-wrap: wrap; 143 | 144 | li { 145 | align-self: flex-start; 146 | margin: 0 -1rem; 147 | width: 100vw; 148 | } 149 | 150 | .nav-item.back-button { 151 | margin-left: -8px; 152 | } 153 | } 154 | } 155 | 156 | form { 157 | margin-top: 0; 158 | margin-bottom: 0; 159 | } 160 | 161 | button.nav-link { 162 | background: inherit; 163 | } 164 | 165 | @include media-breakpoint-down(xs) { 166 | & .nav-tabs { 167 | padding-left: 0; 168 | } 169 | } 170 | } 171 | 172 | .header-extension { 173 | margin-top: -1rem; 174 | margin-bottom: 1rem; 175 | background: $nav-tabs-background; 176 | } 177 | -------------------------------------------------------------------------------- /ui/styles/variables.scss: -------------------------------------------------------------------------------- 1 | $base-font-size: 1rem; 2 | 3 | $navbar-light-color: color_adjust_contrast_AERT($gray-500, white); 4 | $navbar-light-active-color: color_adjust_contrast_AERT($black, white); 5 | 6 | $nav-tabs-background: #ddd; 7 | $link-color: color_adjust_contrast_AERT(#0044ff, white); 8 | 9 | $progress-bar-bg: $link-color; 10 | $pre-background: $gray-200; 11 | 12 | $event-background: $gray-100; 13 | 14 | $font_family_monospace: monospace; 15 | 16 | @mixin anchor_with_contrast($background: $white) { 17 | a { 18 | color: color_adjust_contrast_AERT($link-color, $background); 19 | } 20 | 21 | a:hover { 22 | color: color_adjust_contrast_AERT($link-hover-color, $background); 23 | } 24 | } 25 | --------------------------------------------------------------------------------