Initial commit

main
Manos Pitsidianakis 2020-07-30 11:25:40 +03:00
commit f139cfa350
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
114 changed files with 8898 additions and 0 deletions

3
.gitignore vendored 100644
View File

@ -0,0 +1,3 @@
/target
**/*.rs.bk
_site/

564
Cargo.lock generated 100644
View File

@ -0,0 +1,564 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "block-buffer"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "block-padding"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "byte-tools"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "chrono"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "darling"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"darling_macro 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "darling_core"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "darling_macro"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "derive_builder"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"derive_builder_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "derive_builder_core"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "digest"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "encoding_rs"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fake-simd"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "generic-array"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "handlebars"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "itoa"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libssg"
version = "0.1.1"
dependencies = [
"chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"handlebars 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libssg-site"
version = "0.1.0"
dependencies = [
"libssg 0.1.1",
"linkify 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rss 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "linkify"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "maplit"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "md5"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num-integer"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-traits"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "opaque-debug"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pest"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pest_derive"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pest_generator"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pest_meta"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro2"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quick-xml"
version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"encoding_rs 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "regex"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rss"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"derive_builder 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"quick-xml 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ryu"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde"
version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive"
version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "sha-1"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "strsim"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "typenum"
version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ucd-trie"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "uuid"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "walkdir"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "743ad5a418686aad3b87fd14c43badd828cf26e214a00f92a384291cf22e1811"
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
"checksum darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
"checksum darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
"checksum darling_macro 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
"checksum derive_builder 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0"
"checksum derive_builder_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef"
"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
"checksum encoding_rs 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e8ac63f94732332f44fe654443c46f6375d1939684c17b0afb6cb56b0456e171"
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
"checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
"checksum handlebars 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ba758d094d31274eb49d15da6f326b96bf3185239a6359bf684f3d5321148900"
"checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
"checksum linkify 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03951527dd24d2c59f407502e7d88e0948ef06fac23335b556a4c2bc03c22096"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
"checksum md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e6bcd6433cff03a4bfc3d9834d504467db1f1cf6d0ea765d37d330249ed629d"
"checksum memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223"
"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
"checksum pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e4fb201c5c22a55d8b24fef95f78be52738e5e1361129be1b5e862ecdb6894a"
"checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
"checksum pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9fcf299b5712d06ee128a556c94709aaa04512c4dffb8ead07c5c998447fc0"
"checksum pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df43fd99896fd72c485fe47542c7b500e4ac1e8700bf995544d1317a60ded547"
"checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
"checksum quick-xml 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fe1e430bdcf30c9fdc25053b9c459bb1a4672af4617b6c783d7d91dc17c6bbb0"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
"checksum regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8"
"checksum regex-syntax 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b28dfe3fe9badec5dbf0a79a9cccad2cfc2ab5484bdb3e44cbd1ae8b3ba2be06"
"checksum rss 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99979205510c60f80a119dedbabd0b8426517384edf205322f8bcd51796bcef9"
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
"checksum serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "15913895b61e0be854afd32fd4163fcd2a3df34142cf2cb961b310ce694cbf90"
"checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
"checksum strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
"checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11"
"checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

12
Cargo.toml 100644
View File

@ -0,0 +1,12 @@
[package]
name = "libssg-site"
version = "0.1.0"
authors = ["Manos Pitsidianakis <el13635@mail.ntua.gr>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
linkify = "0.4.0"
rss = "1.9.0"
libssg = { path = "../../libssg/libssg" }

15
README.md 100644
View File

@ -0,0 +1,15 @@
## Build
```sh
FORCE=1 cargo run
```
Check for dead links:
```sh
CHECK=1 cargo run
```
## Run
```
cd _site/
python3 -m http.server 8000
```

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1501
css/default.css 100644

File diff suppressed because it is too large Load Diff

1164
css/default.css.bkp 100644

File diff suppressed because it is too large Load Diff

1077
css/default_tmp.css 100644

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" width="25px" height="25px"><path fill="#77B255" d="M28.938 27.441c-2.554-.89-8.111-.429-9.938 1.331V17c0-.553-.447-1-1-1s-1 .447-1 1v11.772c-1.827-1.76-7.384-2.221-9.938-1.331-.741.259 5.264 8.749 9.507 4.507.168-.168.306-.33.431-.49V35c0 .553.447 1 1 1s1-.447 1-1v-3.542c.125.16.263.322.431.49 4.243 4.242 10.248-4.248 9.507-4.507z"/><path fill="#CCD6DD" d="M12.562 25.65c-.619-.266-1.107-.837-1.378-1.513l-1.266-3.306-3.258-1.393c-1.336-.574-1.876-1.922-1.304-3.259l1.362-3.181-1.364-3.269c-.541-1.35.15-2.868 1.5-3.408l3.272-1.281 1.449-3.384C12.148.32 13.496-.22 14.833.352l3.258 1.396L21.358.382c.675-.271 1.411-.276 2.03-.011.619.265 1.114.819 1.385 1.494l1.274 3.29 3.309 1.417c1.336.572 1.875 1.921 1.305 3.258l-1.451 3.384 1.365 3.267c.541 1.35-.15 2.866-1.5 3.407l-3.271 1.281-1.363 3.183c-.572 1.336-1.922 1.877-3.258 1.305l-3.308-1.417-3.267 1.364c-.676.271-1.427.311-2.046.046z"/><path fill="#E1E8ED" d="M29.356 6.572l-3.309-1.417-.055-.143c-1.565 1.337-5.215 4.354-5.215 4.354l.007.123C20.015 8.879 19.057 8.5 18 8.5V1.709L14.833.353c-1.337-.572-2.685-.032-3.258 1.304l-1.449 3.384-.061.024 4.753 4.754c-.814.813-1.318 1.938-1.318 3.181H6.717l-1.361 3.178c-.572 1.337-.032 2.686 1.304 3.259l3.258 1.394.002.006 4.496-5.142c.822 1.09 2.115 1.805 3.584 1.805h.005c.006 1.979.015 5.273.012 6.801l3.164 1.356c1.336.572 2.686.031 3.258-1.305l1.362-3.18-5.192-4.517c1.14-.816 1.89-2.145 1.89-3.654 0-.071-.018-.137-.021-.208 1.802.182 4.951.472 6.822.642l-.092-.22L30.66 9.83c.571-1.337.031-2.686-1.304-3.258z"/><circle fill="#F4900C" cx="18" cy="13" r="5"/></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 36 36"
width="25px"
height="25px"
version="1.1"
id="svg10"
sodipodi:docname="flowercursor1.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs14" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="779"
inkscape:window-height="480"
id="namedview12"
showgrid="false"
inkscape:zoom="9.44"
inkscape:cx="12.5"
inkscape:cy="12.5"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg10" />
<path
d="M 15.510755,32.30171 C 15.004516,29.64488 11.82678,25.062878 9.3890754,24.360649 L 19.583927,18.474648 c 0.478913,-0.276501 0.642526,-0.887115 0.366024,-1.366025 -0.276498,-0.478912 -0.887112,-0.642526 -1.366025,-0.366025 l -10.1948506,5.886 C 8.999781,20.166369 6.6205187,15.123366 4.5727557,13.356537 c -0.594799,-0.512226 -4.94485538,8.933259 0.8503225,10.486804 0.2294929,0.0615 0.4387901,0.100002 0.6398537,0.128255 l -3.0674632,1.771002 c -0.4789107,0.2765 -0.6425241,0.887113 -0.3660241,1.366025 0.2764992,0.478913 0.8871134,0.642526 1.3660241,0.366025 l 3.0674628,-1.771 c -0.076064,0.188253 -0.1473596,0.388765 -0.2088533,0.618257 -1.5521789,5.795546 8.8028758,6.751029 8.6566768,5.979805 z"
id="path2"
inkscape:connector-curvature="0"
style="fill:#77b255" />
<path
d="m 8.8738062,17.224177 c -0.079136,-0.66907 0.1713655,-1.37719 0.6212973,-1.949884 L 11.725183,12.524906 11.302557,9.006896 C 11.131656,7.5628851 12.029059,6.4212305 13.472934,6.2480977 L 16.90876,5.8371249 19.057797,3.0213655 c 0.898635,-1.1435196 2.558761,-1.3040951 3.701415,-0.4049617 l 2.745379,2.1931344 3.655129,-0.4371287 c 1.44351,-0.1717675 2.585164,0.7256358 2.758298,2.1695114 l 0.420028,3.5195111 2.816491,2.146305 c 0.572193,0.449067 0.944522,1.083961 1.024526,1.75253 0.08,0.668571 -0.152283,1.374252 -0.601342,1.946446 l -2.212223,2.748316 0.427341,3.574178 c 0.172634,1.44301 -0.726135,2.584298 -2.169009,2.759164 l -3.656132,0.435397 -2.146804,2.815625 c -0.898634,1.143519 -2.557029,1.303095 -3.700549,0.404461 l -2.744878,-2.192269 -3.438058,0.411108 c -1.443011,0.172634 -2.586531,-0.726001 -2.759165,-2.169011 L 12.751402,21.12037 9.9366448,18.973065 C 9.3639527,18.523131 8.9538104,17.892746 8.8738071,17.224176 Z"
id="path4"
inkscape:connector-curvature="0"
style="fill:#ccd6dd" />
<path
d="m 33.792839,22.229207 -0.427341,-3.574178 0.09634,-0.119132 c -1.940376,-0.68683 -6.378175,-2.339322 -6.378175,-2.339322 l -0.103017,0.06756 c 0.143771,-0.970974 -0.007,-1.990125 -0.535502,-2.905513 L 32.326324,9.9631208 31.917154,6.5424177 C 31.744022,5.0985408 30.602369,4.201139 29.15886,4.3729051 l -3.65513,0.4371302 -0.05129,-0.040826 -1.740585,6.4932183 c -1.111076,-0.298444 -2.337355,-0.172426 -3.413825,0.449078 l -3.3915,-5.8742496 -3.432729,0.41034 c -1.443882,0.173133 -2.342151,1.3152876 -2.170384,2.7587969 l 0.421761,3.5185117 -0.0042,0.0049 6.701103,1.322649 c -0.532964,1.256875 -0.505676,2.734145 0.228824,4.006337 l 0.0024,0.0044 c -1.710849,0.994688 -4.559036,2.649482 -5.883824,3.410884 l 0.407763,3.418031 c 0.172634,1.44301 1.316152,2.341644 2.759163,2.169011 l 3.434959,-0.410474 1.315837,-6.754903 c 1.276684,0.579254 2.802627,0.564287 4.109457,-0.190212 0.06148,-0.03549 0.109649,-0.08409 0.169634,-0.122187 0.743384,1.651578 2.066737,4.523694 2.855013,6.229026 l 0.144525,-0.189674 3.657497,-0.43503 c 1.443376,-0.174001 2.341645,-1.316154 2.169512,-2.758298 z"
id="path6"
inkscape:connector-curvature="0"
style="fill:#e1e8ed" />
<circle
cx="24.791477"
cy="-11.722854"
r="5"
id="circle8"
style="fill:#f4900c"
transform="rotate(60)" />
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 36 36"
width="25px"
height="25px"
version="1.1"
id="svg10"
sodipodi:docname="flowercursor2.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs14" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="779"
inkscape:window-height="480"
id="namedview12"
showgrid="false"
inkscape:zoom="9.44"
inkscape:cx="12.5"
inkscape:cy="12.5"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg10" />
<path
d="m 4.4115564,21.493855 c 2.0477628,-1.766831 4.4270249,-6.809832 3.8163208,-9.272061 l 10.1948518,5.886 c 0.478914,0.276501 1.089528,0.112887 1.366025,-0.366026 0.276501,-0.47891 0.112888,-1.089525 -0.366026,-1.366025 L 9.2278774,10.489744 C 11.665583,9.7875156 14.843321,5.2055125 15.349558,2.5486833 15.495759,1.7774592 5.140701,2.7329424 6.6928805,8.5284861 6.7543664,8.7579828 6.8256712,8.9584905 6.9017352,9.1467432 L 3.8342709,7.3757431 C 3.3553595,7.0992443 2.7447465,7.2628574 2.4682465,7.7417695 2.1917453,8.2206813 2.3553594,8.8312952 2.8342716,9.1077935 L 5.901734,10.878794 C 5.7006701,10.907047 5.4913738,10.94556 5.2618811,11.00705 -0.53329844,12.560597 3.8167564,22.006079 4.4115564,21.493855 Z"
id="path2"
inkscape:connector-curvature="0"
style="fill:#77b255" />
<path
d="m 14.150609,8.2073222 c 0.539863,-0.4030687 1.278364,-0.5401881 1.999297,-0.4368827 l 3.496079,0.556612 2.835373,-2.1250099 c 1.1651,-0.87001 2.602503,-0.6636635 3.474378,0.5002025 l 2.073826,2.7700262 3.513038,0.4532409 c 1.439634,0.2064808 2.40876,1.5639048 2.201414,3.0030388 l -0.52662,3.474135 2.206129,2.94687 c 0.87051,1.164233 0.664163,2.601636 -0.499703,3.473512 l -2.837972,2.12351 -0.450509,3.512306 c -0.102807,0.720067 -0.466477,1.35996 -1.005473,1.76353 -0.538999,0.403568 -1.266279,0.555245 -1.986343,0.452446 L 25.1573,30.133176 22.275642,32.290353 c -1.163366,0.87101 -2.601135,0.663297 -3.474011,-0.498835 L 16.5965,28.842913 13.084696,28.391539 C 11.645062,28.185058 10.677668,26.828634 10.884148,25.389 L 11.410269,21.915731 9.3352103,19.14384 C 8.4641994,17.980473 8.6706801,16.540838 9.8340465,15.669827 l 2.8811575,-2.156312 0.452243,-3.511304 C 13.270755,9.2812786 13.611613,8.6108924 14.15061,8.2073225 Z"
id="path4"
inkscape:connector-curvature="0"
style="fill:#ccd6dd" />
<path
d="m 22.275642,32.290353 2.881658,-2.157177 0.151342,0.02387 C 24.933266,28.133213 24.145466,23.46372 24.145466,23.46372 l -0.110017,-0.05544 c 0.912774,-0.360977 1.719999,-1.001124 2.248497,-1.916514 l 5.881181,3.3955 2.75783,-2.064703 c 1.163869,-0.871875 1.370215,-2.309276 0.499706,-3.473509 l -2.20613,-2.94687 0.0097,-0.06483 -6.493585,1.739219 c -0.297077,-1.111442 -1.019352,-2.110422 -2.095825,-2.73192 L 28.028333,9.4704046 25.956604,6.7027441 C 25.084725,5.5388721 23.646456,5.3320256 22.482224,6.2025349 l -2.83624,2.1245116 -0.0063,-0.00119 2.205104,6.4646498 c -1.354968,0.166877 -2.620677,0.929144 -3.355177,2.201336 l -0.0026,0.0043 c -1.71685,-0.984294 -4.574037,-2.6235 -5.895824,-3.390099 l -2.7562203,2.062149 c -1.1633664,0.87101 -1.3698472,2.310643 -0.4988372,3.474011 l 2.0729605,2.769525 6.507836,-2.237904 c 0.136693,1.395268 0.912627,2.70929 2.219457,3.463788 0.06148,0.0355 0.127649,0.05291 0.190634,0.08581 -1.058616,1.469579 -2.884265,4.051694 -3.966988,5.587027 l 0.236525,0.03032 2.205495,2.949971 c 0.872378,1.163 2.310646,1.369847 3.473512,0.499703 z"
id="path6"
inkscape:connector-curvature="0"
style="fill:#e1e8ed" />
<circle
cx="5.4704447"
cy="-29.008448"
r="5"
id="circle8"
style="fill:#f4900c"
transform="rotate(120)" />
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 36 36"
width="25px"
height="25px"
version="1.1"
id="svg10"
sodipodi:docname="flowercursor3.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs14" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="779"
inkscape:window-height="480"
id="namedview12"
showgrid="false"
inkscape:zoom="9.44"
inkscape:cx="12.5"
inkscape:cy="12.5"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg10" />
<path
d="M 8.3706614,6.792516 C 10.924663,7.6825151 16.481661,7.2215161 18.308662,5.4615163 l 10e-7,11.7720007 c 0,0.553002 0.447001,1.000002 1,0.999999 0.552999,2e-6 1,-0.446998 0.999999,-1 l 0,-11.7719991 c 1.827,1.7600008 7.384,2.221001 9.938,1.3310005 0.741,-0.2589982 -5.264001,-8.7489999 -9.507,-4.5070012 -0.168007,0.1679967 -0.305999,0.3300023 -0.430999,0.490002 l -10e-7,-3.54200202 c -1e-6,-0.55299888 -0.447,-0.99999868 -1,-0.99999868 -0.553001,-1.1e-6 -1.000001,0.4469998 -0.999999,0.99999908 l 0,3.54200062 c -0.125,-0.16 -0.263001,-0.3219994 -0.431,-0.4900009 C 13.634662,-1.9564829 7.6296624,6.5335161 8.3706614,6.792516 Z"
id="path2"
inkscape:connector-curvature="0"
style="fill:#77b255" />
<path
d="m 24.746663,8.5835166 c 0.618999,0.2660007 1.106998,0.8370016 1.378,1.5130004 l 1.265999,3.305999 3.257999,1.393001 c 1.336001,0.574001 1.876001,1.922002 1.304001,3.259 l -1.362,3.181 1.364001,3.269 c 0.540999,1.35 -0.150001,2.868 -1.500001,3.408 l -3.271999,1.281001 -1.449,3.383999 c -0.573,1.336 -1.921001,1.876 -3.258001,1.304 l -3.258,-1.396 -3.267,1.366 c -0.675,0.271 -1.410999,0.275999 -2.029999,0.011 -0.618999,-0.265003 -1.113996,-0.819007 -1.385001,-1.494 l -1.274,-3.289999 -3.3089994,-1.417001 C 6.6166629,27.089517 6.0776631,25.740516 6.6476609,24.403518 L 8.0986623,21.019516 6.7336616,17.752517 c -0.5409992,-1.35 0.1500014,-2.866 1.5000011,-3.407 l 3.2709993,-1.281 1.362999,-3.1829991 c 0.572,-1.3360011 1.922001,-1.877001 3.258002,-1.3050017 l 3.307999,1.4169996 3.267,-1.3639981 c 0.676,-0.2709988 1.427001,-0.3110002 2.046001,-0.046 z"
id="path4"
inkscape:connector-curvature="0"
style="fill:#ccd6dd" />
<path
d="m 7.9526626,27.661517 3.3089994,1.417001 0.055,0.143001 c 1.565002,-1.337002 5.215002,-4.354003 5.215002,-4.354003 l -0.007,-0.122998 c 0.769002,0.609997 1.726998,0.989001 2.783998,0.988999 l 2e-6,6.791002 3.167,1.355999 c 1.337,0.572003 2.684999,0.032 3.258,-1.303996 l 1.448999,-3.384 0.06099,-0.02401 -4.753001,-4.754 c 0.813999,-0.812997 1.318003,-1.937995 1.318,-3.180997 l 6.783003,9e-6 1.361,-3.178 c 0.572003,-1.337005 0.032,-2.686006 -1.303996,-3.259006 l -3.258001,-1.394 -0.0021,-0.0061 -4.495999,5.142001 c -0.822003,-1.089998 -2.115,-1.805001 -3.584001,-1.805 l -0.005,-1.02e-4 c -0.006,-1.978983 -0.015,-5.272982 -0.012,-6.8009829 L 16.127538,8.5764958 c -1.336,-0.5719999 -2.685999,-0.031001 -3.258,1.3049998 l -1.361999,3.1799994 5.192,4.516999 c -1.139991,0.816013 -1.89,2.145003 -1.89,3.654 -4e-6,0.07099 0.018,0.137002 0.021,0.207999 -1.802,-0.181999 -4.951002,-0.472 -6.8220008,-0.641999 l 0.092005,0.219997 -1.4520024,3.385 c -0.5709985,1.337001 -0.030999,2.686001 1.3040005,3.258001 z"
id="path6"
inkscape:connector-curvature="0"
style="fill:#e1e8ed" />
<circle
cx="-19.308662"
cy="-21.233517"
r="5"
id="circle8"
style="fill:#f4900c"
transform="scale(-1)" />
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 36 36"
width="25px"
height="25px"
version="1.1"
id="svg10"
sodipodi:docname="flowercursor4.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs14" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="779"
inkscape:window-height="480"
id="namedview12"
showgrid="false"
inkscape:zoom="9.44"
inkscape:cx="12.5"
inkscape:cy="12.5"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg10" />
<path
d="m 21.957417,2.0159342 c 0.506239,2.6568298 3.683975,7.2388317 6.12168,7.9410611 L 17.884246,15.842996 c -0.478914,0.276501 -0.642527,0.887116 -0.366025,1.366025 0.276498,0.478913 0.887112,0.642527 1.366025,0.366025 l 10.194851,-5.886 c -0.610706,2.462229 1.768556,7.505232 3.816319,9.272061 0.594799,0.512226 4.944856,-8.933258 -0.850322,-10.486804 -0.229493,-0.0615 -0.43879,-0.100002 -0.639854,-0.128255 L 34.472703,8.575046 C 34.951614,8.2985457 35.115228,7.6879333 34.838728,7.2090213 34.562228,6.7301078 33.951614,6.5664949 33.472704,6.8429963 L 30.405241,8.6139966 C 30.481305,8.4257434 30.5526,8.2252314 30.614094,7.9957392 32.166273,2.2001929 21.811218,1.2447102 21.957417,2.0159342 Z"
id="path2"
inkscape:connector-curvature="0"
style="fill:#77b255" />
<path
d="m 28.594366,17.093468 c 0.07914,0.669069 -0.171366,1.377189 -0.621297,1.949883 l -2.230079,2.749387 0.422625,3.51801 c 0.170901,1.444012 -0.726502,2.585666 -2.170376,2.758798 l -3.435827,0.410974 -2.149037,2.815759 C 17.51174,32.439798 15.851614,32.600374 14.70896,31.70124 L 11.963581,29.508106 8.3084521,29.945235 C 6.8649422,30.117003 5.723288,29.219599 5.5501545,27.775723 L 5.130126,24.256213 2.3136353,22.109908 C 1.7414424,21.660841 1.3691136,21.025946 1.2891095,20.357377 c -0.08,-0.66857 0.1522829,-1.374252 0.6013414,-1.946446 L 4.1026737,15.662615 3.6753328,12.088437 C 3.5026995,10.645427 4.4014687,9.5041394 5.8443419,9.3292729 L 9.5004743,8.893876 11.647278,6.0782512 c 0.898635,-1.143519 2.55703,-1.3030949 3.700549,-0.4044609 l 2.744878,2.1922685 3.438058,-0.4111078 c 1.443011,-0.172634 2.586531,0.7260012 2.759166,2.1690116 l 0.426841,3.5733114 2.814757,2.147306 c 0.572692,0.449933 0.982835,1.080319 1.062838,1.748888 z"
id="path4"
inkscape:connector-curvature="0"
style="fill:#ccd6dd" />
<path
d="m 3.6753328,12.088437 0.4273409,3.574178 -0.096343,0.119132 c 1.9403787,0.68683 6.3781778,2.339323 6.3781778,2.339323 l 0.10302,-0.06756 c -0.143772,0.970973 0.007,1.990124 0.5355,2.905512 l -5.8811788,3.395503 0.4091705,3.420702 c 0.1731308,1.443877 1.3147867,2.341277 2.7582936,2.169512 l 3.6551297,-0.43713 0.05129,0.04081 1.740584,-6.493219 c 1.111076,0.298445 2.337355,0.172426 3.413825,-0.449077 l 3.391493,5.874257 3.432729,-0.410339 c 1.443882,-0.173134 2.342149,-1.315291 2.170384,-2.758797 l -0.421761,-3.518512 0.0042,-0.0049 -6.701103,-1.322649 c 0.532964,-1.256875 0.505676,-2.734144 -0.228825,-4.006336 l -0.0024,-0.0044 c 1.71085,-0.994688 4.559037,-2.649482 5.883824,-3.410884 L 24.290884,9.6255762 C 24.11825,8.1825664 22.974732,7.2839324 21.531721,7.4565654 l -3.43496,0.4104739 -1.315836,6.7549037 c -1.276683,-0.579255 -2.802627,-0.564287 -4.109457,0.190212 -0.06148,0.03549 -0.109647,0.08409 -0.169632,0.122186 C 11.758452,13.282763 10.435099,10.410647 9.6468229,8.7053153 L 9.5023024,8.8949924 5.8448052,9.3300215 C 4.4014291,9.5040228 3.5031606,10.646176 3.6752938,12.08832 Z"
id="path6"
inkscape:connector-curvature="0"
style="fill:#e1e8ed" />
<circle
cx="-23.66256"
cy="3.5667133"
r="5"
id="circle8"
style="fill:#f4900c"
transform="rotate(-120)" />
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 36 36"
width="25px"
height="25px"
version="1.1"
id="svg10"
sodipodi:docname="flowercursor5.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs14" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="779"
inkscape:window-height="480"
id="namedview12"
showgrid="false"
inkscape:zoom="9.44"
inkscape:cx="12.5"
inkscape:cy="12.5"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg10" />
<path
d="m 33.056616,12.823789 c -2.047763,1.766831 -4.427025,6.809832 -3.816321,9.272061 l -10.194852,-5.886 c -0.478913,-0.276501 -1.089528,-0.112886 -1.366024,0.366026 -0.276502,0.478911 -0.112889,1.089525 0.366025,1.366025 l 10.194851,5.886 c -2.437706,0.702227 -5.615443,5.28423 -6.121681,7.941059 -0.146201,0.771224 10.208857,-0.184258 8.656678,-5.979802 -0.06149,-0.229497 -0.132791,-0.430004 -0.208855,-0.618257 l 3.067464,1.770999 c 0.478912,0.276499 1.089525,0.112887 1.366025,-0.366025 0.276501,-0.478913 0.112887,-1.089526 -0.366025,-1.366024 L 31.566438,23.43885 c 0.201064,-0.02825 0.41036,-0.06677 0.639853,-0.128256 5.79518,-1.553547 1.445125,-10.999029 0.850325,-10.486805 z"
id="path2"
inkscape:connector-curvature="0"
style="fill:#77b255" />
<path
d="m 23.317563,26.110322 c -0.539861,0.403072 -1.278364,0.540187 -1.999297,0.436883 l -3.496078,-0.556612 -2.835374,2.125009 c -1.1651,0.870011 -2.602503,0.663664 -3.474377,-0.500202 L 9.4386096,24.845374 5.9255722,24.392133 C 4.4859382,24.185652 3.5168123,22.828228 3.7241582,21.389094 L 4.2507785,17.914959 2.0446492,14.968089 C 1.1741388,13.803857 1.3804864,12.366453 2.5443529,11.494577 L 5.3823237,9.3710668 5.832833,5.8587618 C 5.93564,5.1386947 6.2993108,4.498801 6.8383065,4.095231 7.3773051,3.6916639 8.1045851,3.5399858 8.8246489,3.6427849 L 12.310872,4.184468 15.19253,2.027291 c 1.163367,-0.8710099 2.601136,-0.6632967 3.474011,0.4988349 l 2.205131,2.9486051 3.511804,0.4513741 c 1.439634,0.2064813 2.407029,1.5629055 2.200548,3.002539 l -0.526121,3.4732679 2.075059,2.771892 c 0.871011,1.163367 0.66453,2.603002 -0.498836,3.474014 l -2.881158,2.156311 -0.452243,3.511304 c -0.103308,0.720932 -0.444166,1.391319 -0.983163,1.794888 z"
id="path4"
inkscape:connector-curvature="0"
style="fill:#ccd6dd" />
<path
d="m 15.19253,2.027291 -2.881658,2.157177 -0.151343,-0.023869 c 0.375377,2.0238322 1.163176,6.6933254 1.163176,6.6933254 l 0.110018,0.05544 c -0.912773,0.360976 -1.719998,1.001124 -2.248497,1.916513 L 5.3030449,9.4303759 2.5452153,11.495079 c -1.1638687,0.871874 -1.370212,2.309277 -0.4997057,3.473508 l 2.2061306,2.94687 -0.0097,0.06482 6.4935843,-1.73922 c 0.297077,1.111443 1.019352,2.110422 2.095825,2.731921 l -3.3915094,5.874248 2.0717284,2.767661 c 0.87188,1.163871 2.31015,1.370715 3.47438,0.500209 l 2.836241,-2.124512 0.0063,0.0012 -2.205104,-6.46465 c 1.354968,-0.166877 2.620676,-0.929143 3.355177,-2.201336 l 0.0026,-0.0043 c 1.71685,0.984295 4.574037,2.623501 5.895824,3.390099 l 2.756164,-2.062158 c 1.163366,-0.871011 1.369847,-2.310643 0.498837,-3.474011 l -2.072961,-2.769526 -6.507836,2.237905 c -0.136692,-1.395268 -0.912627,-2.70929 -2.219457,-3.463788 -0.06148,-0.0355 -0.127648,-0.05291 -0.190632,-0.08581 1.058616,-1.4695785 2.884265,-4.0516938 3.966988,-5.5870268 l -0.236526,-0.03032 -2.205495,-2.949971 C 17.793747,1.3639017 16.355479,1.157055 15.192612,2.0271987 Z"
id="path6"
inkscape:connector-curvature="0"
style="fill:#e1e8ed" />
<circle
cx="-5.51542"
cy="20.598763"
r="5"
id="circle8"
style="fill:#f4900c"
transform="rotate(-60)" />
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

256
css/hex-grid.css 100644
View File

@ -0,0 +1,256 @@
.hex-grid {
display: flex;
justify-content: center; }
.hex-grid__list {
--amount: 5;
position: relative;
padding: 0;
margin: 0;
list-style-type: none;
display: grid;
grid-template-columns: repeat(var(--amount), 1fr 2fr) 1fr;
grid-gap: 2.5rem 5rem; }
.hex-grid__item {
position: relative;
grid-column: 1 / span 3;
grid-row: calc(var(--counter) + var(--counter))/span 2;
filter: drop-shadow(0 0 10px rgba(68, 68, 68, 0.08));
height: 0;
padding-bottom: 90%; }
.hex-grid__content {
position: absolute;
height: 100%;
width: 100%;
font-size: 1.125rem;
color: #111111;
background-color: white;
clip-path: polygon(75% 0, 100% 50%, 75% 100%, 25% 100%, 0 50%, 25% 0);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 2rem 25%;
text-decoration: none;
text-align: center;
transition: transform .24s ease-out; }
@media screen and (min-width: 1440px) {
.hex-grid__list {
--amount: 5;
--counter: 1; }
.hex-grid__item:nth-of-type(5n + 1) {
grid-column: 1 / span 3; }
.hex-grid__item:nth-of-type(5n + 2) {
grid-column: 3 / span 3;
grid-row: calc(var(--counter) + var(--counter) - 1)/span 2; }
.hex-grid__item:nth-of-type(5n + 3) {
grid-column: 5 / span 3; }
.hex-grid__item:nth-of-type(5n + 4) {
grid-column: 7 / span 3;
grid-row: calc(var(--counter) + var(--counter) - 1)/span 2; }
.hex-grid__item:nth-of-type(5n + 5) {
grid-column: 9 / span 3; }
.hex-grid__item:nth-of-type(n + 6) {
--counter: 2; }
.hex-grid__item:nth-of-type(n + 11) {
--counter: 3; }
.hex-grid__item:nth-of-type(n + 16) {
--counter: 4; }
.hex-grid__item:nth-of-type(n + 21) {
--counter: 5; }
.hex-grid__item:nth-of-type(n + 26) {
--counter: 6; }
.hex-grid__item:nth-of-type(n + 31) {
--counter: 7; }
.hex-grid__item:nth-of-type(n + 36) {
--counter: 8; }
.hex-grid__item:nth-of-type(n + 41) {
--counter: 9; }
.hex-grid__item:nth-of-type(n + 46) {
--counter: 10; }
.hex-grid__item:nth-of-type(n + 51) {
--counter: 11; }
.hex-grid__item:nth-of-type(n + 56) {
--counter: 12; }
.hex-grid__item:nth-of-type(n + 61) {
--counter: 13; }
.hex-grid__item:nth-of-type(n + 66) {
--counter: 14; }
.hex-grid__item:nth-of-type(n + 71) {
--counter: 15; }
.hex-grid__item:nth-of-type(n + 76) {
--counter: 16; }
.hex-grid__item:nth-of-type(n + 81) {
--counter: 17; }
.hex-grid__item:nth-of-type(n + 86) {
--counter: 18; }
.hex-grid__item:nth-of-type(n + 91) {
--counter: 19; }
.hex-grid__item:nth-of-type(n + 96) {
--counter: 20; }
.hex-grid__item:nth-of-type(n + 101) {
--counter: 21; } }
@media screen and (min-width: 1120px) and (max-width: 1439px) {
.hex-grid__list {
--amount: 4;
--counter: 1; }
.hex-grid__item:nth-of-type(4n + 1) {
grid-column: 1 / span 3; }
.hex-grid__item:nth-of-type(4n + 2) {
grid-column: 3 / span 3;
grid-row: calc(var(--counter) + var(--counter) - 1)/span 2; }
.hex-grid__item:nth-of-type(4n + 3) {
grid-column: 5 / span 3; }
.hex-grid__item:nth-of-type(4n + 4) {
grid-column: 7 / span 3;
grid-row: calc(var(--counter) + var(--counter) - 1)/span 2; }
.hex-grid__item:nth-of-type(n + 5) {
--counter: 2; }
.hex-grid__item:nth-of-type(n + 9) {
--counter: 3; }
.hex-grid__item:nth-of-type(n + 13) {
--counter: 4; }
.hex-grid__item:nth-of-type(n + 17) {
--counter: 5; }
.hex-grid__item:nth-of-type(n + 21) {
--counter: 6; }
.hex-grid__item:nth-of-type(n + 25) {
--counter: 7; }
.hex-grid__item:nth-of-type(n + 29) {
--counter: 8; }
.hex-grid__item:nth-of-type(n + 33) {
--counter: 9; }
.hex-grid__item:nth-of-type(n + 37) {
--counter: 10; }
.hex-grid__item:nth-of-type(n + 41) {
--counter: 11; }
.hex-grid__item:nth-of-type(n + 45) {
--counter: 12; }
.hex-grid__item:nth-of-type(n + 49) {
--counter: 13; }
.hex-grid__item:nth-of-type(n + 53) {
--counter: 14; }
.hex-grid__item:nth-of-type(n + 57) {
--counter: 15; }
.hex-grid__item:nth-of-type(n + 61) {
--counter: 16; }
.hex-grid__item:nth-of-type(n + 65) {
--counter: 17; }
.hex-grid__item:nth-of-type(n + 69) {
--counter: 18; }
.hex-grid__item:nth-of-type(n + 73) {
--counter: 19; }
.hex-grid__item:nth-of-type(n + 77) {
--counter: 20; }
.hex-grid__item:nth-of-type(n + 81) {
--counter: 21; } }
@media screen and (min-width: 840px) and (max-width: 1119px) {
.hex-grid__list {
--amount: 3;
--counter: 1;
grid-gap: 1.5rem 3rem; }
.hex-grid__item:nth-of-type(3n + 1) {
grid-column: 1 / span 3; }
.hex-grid__item:nth-of-type(3n + 2) {
grid-column: 3 / span 3;
grid-row: calc(var(--counter) + var(--counter) - 1)/span 2; }
.hex-grid__item:nth-of-type(3n + 3) {
grid-column: 5 / span 3; }
.hex-grid__item:nth-of-type(n + 4) {
--counter: 2; }
.hex-grid__item:nth-of-type(n + 7) {
--counter: 3; }
.hex-grid__item:nth-of-type(n + 10) {
--counter: 4; }
.hex-grid__item:nth-of-type(n + 13) {
--counter: 5; }
.hex-grid__item:nth-of-type(n + 16) {
--counter: 6; }
.hex-grid__item:nth-of-type(n + 19) {
--counter: 7; }
.hex-grid__item:nth-of-type(n + 22) {
--counter: 8; }
.hex-grid__item:nth-of-type(n + 25) {
--counter: 9; }
.hex-grid__item:nth-of-type(n + 28) {
--counter: 10; }
.hex-grid__item:nth-of-type(n + 31) {
--counter: 11; }
.hex-grid__item:nth-of-type(n + 34) {
--counter: 12; }
.hex-grid__item:nth-of-type(n + 37) {
--counter: 13; }
.hex-grid__item:nth-of-type(n + 40) {
--counter: 14; }
.hex-grid__item:nth-of-type(n + 43) {
--counter: 15; }
.hex-grid__item:nth-of-type(n + 46) {
--counter: 16; }
.hex-grid__item:nth-of-type(n + 49) {
--counter: 17; }
.hex-grid__item:nth-of-type(n + 52) {
--counter: 18; }
.hex-grid__item:nth-of-type(n + 55) {
--counter: 19; }
.hex-grid__item:nth-of-type(n + 58) {
--counter: 20; }
.hex-grid__item:nth-of-type(n + 61) {
--counter: 21; } }
@media screen and (min-width: 480px) and (max-width: 839px) {
.hex-grid__list {
--amount: 2;
--counter: 1;
grid-gap: 1.5rem 3rem; }
.hex-grid__item:nth-of-type(2n + 1) {
grid-column: 1 / span 3; }
.hex-grid__item:nth-of-type(2n + 2) {
grid-column: 3 / span 3;
grid-row: calc(var(--counter) + var(--counter) - 1)/span 2; }
.hex-grid__item:nth-of-type(n + 3) {
--counter: 2; }
.hex-grid__item:nth-of-type(n + 5) {
--counter: 3; }
.hex-grid__item:nth-of-type(n + 7) {
--counter: 4; }
.hex-grid__item:nth-of-type(n + 9) {
--counter: 5; }
.hex-grid__item:nth-of-type(n + 11) {
--counter: 6; }
.hex-grid__item:nth-of-type(n + 13) {
--counter: 7; }
.hex-grid__item:nth-of-type(n + 15) {
--counter: 8; }
.hex-grid__item:nth-of-type(n + 17) {
--counter: 9; }
.hex-grid__item:nth-of-type(n + 19) {
--counter: 10; }
.hex-grid__item:nth-of-type(n + 21) {
--counter: 11; }
.hex-grid__item:nth-of-type(n + 23) {
--counter: 12; }
.hex-grid__item:nth-of-type(n + 25) {
--counter: 13; }
.hex-grid__item:nth-of-type(n + 27) {
--counter: 14; }
.hex-grid__item:nth-of-type(n + 29) {
--counter: 15; }
.hex-grid__item:nth-of-type(n + 31) {
--counter: 16; }
.hex-grid__item:nth-of-type(n + 33) {
--counter: 17; }
.hex-grid__item:nth-of-type(n + 35) {
--counter: 18; }
.hex-grid__item:nth-of-type(n + 37) {
--counter: 19; }
.hex-grid__item:nth-of-type(n + 39) {
--counter: 20; }
.hex-grid__item:nth-of-type(n + 41) {
--counter: 21; } }
@media screen and (max-width: 479px) {
.hex-grid__list {
--amount: 1;
grid-gap: 1.5rem 3rem; } }

125
css/hex-grid.scss 100644
View File

@ -0,0 +1,125 @@
$amount: 1;
$block: '.hex-grid';
@mixin grid-item($amount) {
@for $i from 1 through $amount {
&:nth-of-type(#{$amount}n + #{$i}) {
grid-column: #{$i + $i - 1} / span 3;
@if $i % 2 == 0 {
grid-row: calc(var(--counter) + var(--counter) - 1) / span 2;
}
}
}
@for $i from 1 through 20 {
&:nth-of-type(n + #{$i * $amount + 1}) {
--counter: #{$i + 1};
}
}
}
#{$block} {
display: flex;
justify-content: center;
&__list {
--amount: 5;
position: relative;
padding: 0;
margin: 0;
list-style-type: none;
display: grid;
grid-template-columns: repeat(var(--amount), 1fr 2fr) 1fr;
grid-gap: 2.5rem 5rem;
}
&__item {
position: relative;
grid-column: 1 / span 3;
grid-row: calc(var(--counter) + var(--counter)) / span 2;
filter: drop-shadow(0 0 10px rgba(#444, .08));
height: 0;
padding-bottom: 90%;
}
&__content {
position: absolute;
height: 100%;
width: 100%;
font-size: 1.125rem;
color: #111111;
background-color: white;
clip-path: polygon(75% 0, 100% 50%, 75% 100%, 25% 100%, 0 50%, 25% 0);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 2rem 25%;
text-decoration: none;
text-align: center;
transition: transform .24s ease-out;
}
}
@media screen and (min-width: 1440px) {
#{$block} {
&__list {
--amount: 5;
--counter: 1;
}
&__item {
@include grid-item(5);
}
}
}
@media screen and (min-width: 1120px) and (max-width: 1439px) {
#{$block} {
&__list {
--amount: 4;
--counter: 1;
}
&__item {
@include grid-item(4);
}
}
}
@media screen and (min-width: 840px) and (max-width: 1119px) {
#{$block} {
&__list {
--amount: 3;
--counter: 1;
grid-gap: 1.5rem 3rem;
}
&__item {
@include grid-item(3);
}
}
}
@media screen and (min-width: 480px) and (max-width: 839px) {
#{$block} {
&__list {
--amount: 2;
--counter: 1;
grid-gap: 1.5rem 3rem;
}
&__item {
@include grid-item(2);
}
}
}
@media screen and (max-width: 479px) {
#{$block} {
&__list {
--amount: 1;
grid-gap: 1.5rem 3rem;
}
}
}

226
css/manpage.css 100644
View File

@ -0,0 +1,226 @@
/* $Id: example.style.css,v 1.49 2011/12/15 12:18:57 kristaps Exp $ */
/*
* This is an example style-sheet provided for mandoc(1) and the -Thtml
* or -Txhtml output mode.
* It mimics the appearance of the legacy man.cgi output.
* See mdoc(7) and man(7) for macro explanations.
*/
/*
.Bd pre {
background: teal;
color: white;
padding: 5px;
border-color: teal;
border: 2px solid #486262;
border-left-width: 5px;
overflow-x: auto;
}
*/
:root {
--color-cm: #0b5b00;
--color-pa: green;
--color-ar: #b0141a;
}
@media (prefers-color-scheme: dark) {
:root {
--color-cm: #63ff2b;
--color-pa: #0f0;
--color-ar: #fbb7ba;
}
}
table.Nm tbody tr > * {
display: inline;
}
a.permalink {
text-decoration: none;
color: var(--color-text);
}
@media (prefers-color-scheme: dark) {
a.permalink {
text-decoration: dotted underline;
}
}
h1.Sh {
font-size: 10pt;
margin: 20px 0;
}
section.Sh {
border-left: 1px dashed #979696;
padding-left: 2rem;
overflow-x: auto;
}
div.Nd {
display: inline;
}
dl.Bl-tag {
/*display: flex;
flex-wrap: wrap;*/
display: grid;
width: 100%;
max-width: 100%;
overflow-x: auto;
grid-template-columns: minmax(auto, 1fr) minmax(auto, 1fr);
grid-template-rows: auto;
}
dt {
margin: .5rem 0;
overflow-x: auto;
grid-column: 1 / span 1;
}
dd {
margin-left: auto;
margin: .5rem 0;
overflow-x: auto;
grid-column: 2 / span 1;
}
.Cm {
color: var(--color-cm);
}
.Ar {
color: var(--color-ar);
font-style: normal;
}
.Em {
font-style: normal;
color: var(--color-pa);
}
.Pa {
color: var(--color-pa);
}
.Pa::after {
content: " 📁";
filter: grayscale();
white-space: pre;
}
@media (prefers-color-scheme: dark) {
.Pa::after {
filter: invert(100%) grayscale(100%);
}
}
.Pa:hover::after {
content: " 📂";
white-space: pre;
display: inline-block;
user-select: none;
cursor:pointer;
}
.Bd.Pp {
padding: .2rem;
}
.Bd.Bd-indent {
margin: 0 2rem;
background: darksalmon;
padding: .7rem;
border: 2px inset #792323;
color: #3c0303;
box-shadow: inset 2px 2px #c83333;
overflow-x:auto;
}
.Xr {
font-weight: 800;
}
code.Nm::after {
white-space: pre;
}
ul.Bl-compact {
list-style: inside lower-greek;
}
ol.Bl-enum li {
margin: .2rem 0;
}
.Bd pre {
background: #ecbc2a;
color: #3c2b0c;
padding: 20px;
border: solid #b79328;
overflow-x: auto;
max-width: max-content;
margin: auto;
box-shadow: 5px 5px #737373;
}
.tbl {
border-spacing: 0;
border: solid black;
border-width: 1px 1px 0px 0px;
margin: auto;
margin-bottom: 1rem;
box-shadow: 1px 1px grey;
}
table.tbl td {
border: solid #000;
border-width: 0 0 1px 1px;
border-spacing: 0;
padding: 0.2rem;
}
hr {
margin: initial;
max-width: 50em;
margin-bottom:1rem;
clear: both;
}
.foot {
width: 100%;
font-size: 80%;
}
.foot .foot-date {
text-align: left;
}
.foot .foot-os {
text-align: right;
}
.head {
width: 100%;
font-size: 80%;
}
.head .head-ltitle {
text-align:left;
}
.head .head-vol {
text-align:center;
}
.head .head-rtitle {
text-align:right;
}
code.Li {
background: revert;
border: revert;
text-align: revert;
margin: revert;
color: revert;
}

361
css/mvp.css 100644
View File

@ -0,0 +1,361 @@
/* MVP.css v1.0.1 - by Andy Brewer */
:root {
--border-radius: 5px;
--box-shadow: 2px 2px 10px;
--color: #118bee;
--color-accent: #118bee0b;
--color-bg: #fff;
--color-bg-secondary: #e9e9e9;
--color-secondary: #920de9;
--color-secondary-accent: #920de90b;
--color-shadow: #f4f4f4;
--color-text: #000;
--color-text-secondary: #999;
--hover-brightness: 1.2;
--justify-important: center;
--justify-normal: left;
--line-height: 150%;
--width-card: 285px;
--width-card-medium: 460px;
--width-card-wide: 800px;
--width-content: 1080px;
}
@media (prefers-color-scheme: dark) {
:root {
--color-accent: #118aee7f;
--color-bg: #333333;
--color-bg-secondary: #555;
--color-secondary: #6df216;
--color-secondary-accent: #6df2167f;
--color-shadow: #bbbbbb20;
--color-text: #fff;
--color-text-secondary: #666;
}
}
/* Layout */
article aside {
background: var(--color-secondary-accent);
border-left: 4px solid var(--color-secondary);
padding: 0.01rem 0.8rem;
}
body {
background: var(--color-bg);
color: var(--color-text);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
line-height: var(--line-height);
margin: 0;
overflow-x: hidden;
padding: 1rem 0;
}
footer,
header,
main {
margin: 0 auto;
max-width: var(--width-content);
padding: 2rem 1rem;
}
hr {
background-color: var(--color-bg-secondary);
border: none;
height: 1px;
margin: 4rem 0;
}
section {
display: flex;
flex-wrap: wrap;
justify-content: var(--justify-important);
}
section aside {
border: 1px solid var(--color-bg-secondary);
border-radius: var(--border-radius);
box-shadow: var(--box-shadow) var(--color-shadow);
margin: 1rem;
padding: 1.25rem;
width: var(--width-card);
}
section aside:hover {
box-shadow: var(--box-shadow) var(--color-bg-secondary);
}
section aside img {
max-width: 100%;
}
/* Headers */
article header,
div header,
main header {
padding-top: 0;
}
header {
text-align: var(--justify-important);
}
header a b,
header a em,
header a i,
header a strong {
margin-left: 1rem;
margin-right: 1rem;
}
header nav img {
margin: 1rem 0;
}
section header {
padding-top: 0;
width: 100%;
}
/* Nav */
nav {
align-items: center;
display: flex;
font-weight: bold;
justify-content: space-between;
margin-bottom: 7rem;
}
nav ul {
list-style: none;
padding: 0;
}
nav ul li {
display: inline-block;
margin: 0 0.5rem;
}
/* Typography */
code {
display: inline-block;
margin: 0 0.1rem;
padding: 0rem 0.5rem;
}
code,
samp {
background-color: var(--color-accent);
color: var(--color-text);
border-radius: var(--border-radius);
text-align: var(--justify-normal);
}
h1,
h2,
h3,
h4,
h5,
h6 {
line-height: var(--line-height);
}
mark {
padding: 0.1rem;
}
ol li,
ul li {
padding: 0.2rem 0;
}
p {
margin: 0.75rem 0;
padding: 0;
}
samp {
display: block;
margin: 1rem 0;
max-width: var(--width-card-wide);
padding: 1rem;
}
small {
color: var(--color-text-secondary);
}
sup {
background-color: var(--color-secondary);
border-radius: var(--border-radius);
color: var(--color-bg);
font-size: xx-small;
font-weight: bold;
margin: 0.2rem;
padding: 0.2rem 0.3rem;
position: relative;
top: -2px;
}
/* Links */
a {
color: var(--color-secondary);
font-weight: bold;
text-decoration: none;
}
a:hover {
filter: brightness(var(--hover-brightness));
text-decoration: underline;
}
a b,
a em,
a i,
a strong,
button {
border-radius: var(--border-radius);
display: inline-block;
font-size: medium;
font-weight: bold;
margin: 1.5rem 0 0.5rem 0;
padding: 1rem 2rem;
}
button:hover {
cursor: pointer;
filter: brightness(var(--hover-brightness));
}
a b,
a strong,
button {
background-color: var(--color);
border: 2px solid var(--color);
color: var(--color-bg);
}
a em,
a i {
border: 2px solid var(--color);
border-radius: var(--border-radius);
color: var(--color);
display: inline-block;
padding: 1rem 2rem;
}
/* Images */
figure {
margin: 0;
padding: 0;
}
figure figcaption {
color: var(--color-text-secondary);
}
/* Forms */
form {
border: 1px solid var(--color-bg-secondary);
border-radius: var(--border-radius);
box-shadow: var(--box-shadow) var(--color-shadow);
display: block;
max-width: var(--width-card-wide);
min-width: var(--width-card);
padding: 1.5rem;
text-align: var(--justify-normal);
}
form header {
margin: 1.5rem 0;
padding: 1.5rem 0;
}
input,
label,
select,
textarea {
display: block;
font-size: inherit;
max-width: var(--width-card-wide);
}
input,
select,
textarea {
margin-bottom: 1rem;
}
input,
textarea {
border: 1px solid var(--color-bg-secondary);
border-radius: var(--border-radius);
padding: 0.4rem 0.8rem;
}
label {
font-weight: bold;
margin-bottom: 0.2rem;
}
/* Tables */
table {
border: 1px solid var(--color-bg-secondary);
border-radius: var(--border-radius);
border-spacing: 0;
display: block;
overflow-x: scroll;
overflow-y: hidden;
padding: 0;
}
table td,
table th,
table tr {
padding: 0.4rem 0.8rem;
text-align: var(--justify-important);
}
table thead {
background-color: var(--color);
border-collapse: collapse;
border-radius: var(--border-radius);
color: var(--color-bg);
margin: 0;
padding: 0;
}
table thead th:first-child {
border-top-left-radius: var(--border-radius);
}
table thead th:last-child {
border-top-right-radius: var(--border-radius);
}
table thead th:first-child,
table tr td:first-child {
text-align: var(--justify-normal);
}
/* Quotes */
blockquote {
display: block;
font-size: x-large;
line-height: var(--line-height);
margin: 1rem auto;
max-width: var(--width-card-medium);
padding: 1.5rem 1rem;
text-align: var(--justify-important);
}
blockquote footer {
color: var(--color-text-secondary);
display: block;
font-size: small;
line-height: var(--line-height);
padding: 1.5rem 0;
}
/* Custom styles */

78
css/syntax.css 100644
View File

@ -0,0 +1,78 @@
:root {
--color-other: #007020;
--color-datatype: #902000;
}
@media (prefers-color-scheme: dark) {
:root {
--color-other: #3bff2a;
}
}
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
a.sourceLine:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre-wrap; position: relative; color: black; }
pre.sourceCode code.sourceCode { white-space: pre; padding: .5rem; }
pre.sourceCode {
margin: 0;
background: #80808014;
width: min-content;
border-radius: 2px;
border: 1px solid #80808014;
}
@media screen {
div.sourceCode { overflow: auto; }
div.sourceCode:hover { overflow:visible; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
{ position: relative; left: -4em; }
pre.numberSource a.sourceLine::before
{ content: attr(title);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; pointer-events: all; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
a.sourceLine::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: var(--color-other); font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: var(--color-datatype); } /* DataType */
code span.dv { color: #0081A1; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #8F5C87; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #A45B70; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

2
images/bee.svg 100644
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 47.5 47.5" style="enable-background:new 0 0 47.5 47.5;" id="svg2" xml:space="preserve"><defs id="defs6"><clipPath id="clipPath18"><path d="M 0,38 38,38 38,0 0,0 0,38 z" id="path20"/></clipPath><clipPath id="clipPath38"><path d="M 8.719,17 C 8.719,10.867 13.322,4 19,4 l 0,0 c 5.679,0 10.281,6.867 10.281,13 l 0,0 c 0,6.133 -4.602,8.923 -10.281,8.923 l 0,0 C 13.322,25.923 8.719,23.133 8.719,17" id="path40"/></clipPath><clipPath id="clipPath60"><path d="M 0,38 38,38 38,0 0,0 0,38 z" id="path62"/></clipPath></defs><g transform="matrix(1.25,0,0,-1.25,0,47.5)" id="g12"><g id="g14"><g clip-path="url(#clipPath18)" id="g16"><g transform="translate(20,4)" id="g22"><path d="m 0,0 c 0,-1.657 -0.447,-3 -1,-3 -0.552,0 -1,1.343 -1,3 0,1.657 0.448,3 1,3 0.553,0 1,-1.343 1,-3" id="path24" style="fill:#292f33;fill-opacity:1;fill-rule:nonzero;stroke:none"/></g><g transform="translate(26.7529,35.7529)" id="g26"><path d="m 0,0 c -0.586,0.586 -1.693,0.428 -2.475,-0.354 -0.611,-0.611 -1.948,-2.53 -2.222,-3.619 -0.884,0.195 -1.93,0.22 -3.056,0.22 -1.125,0 -2.172,-0.025 -3.055,-0.219 -0.275,1.089 -1.611,3.007 -2.223,3.618 -0.781,0.782 -1.888,0.94 -2.474,0.354 -0.586,-0.586 -0.428,-1.693 0.353,-2.475 0.511,-0.51 1.937,-1.529 3.027,-2.011 -0.82,-0.533 -1.315,-1.451 -1.315,-3.032 0,-3.589 2.546,-7.312 5.687,-7.312 3.142,0 5.688,3.723 5.688,7.312 0,1.581 -0.496,2.499 -1.316,3.032 1.091,0.482 2.517,1.5 3.027,2.011 C 0.428,-1.693 0.586,-0.586 0,0" id="path28" style="fill:#292f33;fill-opacity:1;fill-rule:nonzero;stroke:none"/></g><g transform="translate(29.2813,17)" id="g30"><path d="m 0,0 c 0,-6.134 -4.603,-13 -10.281,-13 -5.678,0 -10.281,6.866 -10.281,13 0,6.133 4.603,8.923 10.281,8.923 C -4.603,8.923 0,6.133 0,0" id="path32" style="fill:#292f33;fill-opacity:1;fill-rule:nonzero;stroke:none"/></g></g></g><g id="g34"><g clip-path="url(#clipPath38)" id="g36"><path d="m 30,18 -22,0 0,4 22,0 0,-4 z" id="path42" style="fill:#ffcc4d;fill-opacity:1;fill-rule:nonzero;stroke:none"/><path d="m 30,10 -22,0 0,4 22,0 0,-4 z" id="path44" style="fill:#ffcc4d;fill-opacity:1;fill-rule:nonzero;stroke:none"/><path d="M 30,2 8,2 8,6 30,6 30,2 z" id="path46" style="fill:#ffcc4d;fill-opacity:1;fill-rule:nonzero;stroke:none"/><g transform="translate(19,22.9995)" id="g48"><path d="m 0,0 c 0,-2.647 -7.858,-10 -12,-10 -4.142,0 -6,5.354 -6,8 0,2.646 1.858,1.584 6,1.584 4.143,0 12,3.061 12,0.416" id="path50" style="fill:#292f33;fill-opacity:1;fill-rule:nonzero;stroke:none"/></g><g transform="translate(19,22.9995)" id="g52"><path d="m 0,0 c 0,-2.647 7.857,-10 12,-10 4.143,0 6,5.354 6,8 0,2.646 -1.857,1.584 -6,1.584 C 7.857,-0.416 0,2.645 0,0" id="path54" style="fill:#292f33;fill-opacity:1;fill-rule:nonzero;stroke:none"/></g></g></g><g id="g56"><g clip-path="url(#clipPath60)" id="g58"><g transform="translate(19,23.4946)" id="g64"><path d="m 0,0 c 0,-2.647 -7.858,-8.584 -12,-8.584 -4.142,0 -6,2.443 -6,5.089 C -18,-0.849 -16.142,1 -12,1 -7.857,1 0,2.645 0,0" id="path66" style="fill:#ccd6dd;fill-opacity:1;fill-rule:nonzero;stroke:none"/></g><g transform="translate(19,23.4946)" id="g68"><path d="m 0,0 c 0,-2.647 7.857,-8.584 12,-8.584 4.143,0 6,2.443 6,5.089 C 18,-0.849 16.143,1 12,1 7.857,1 0,2.645 0,0" id="path70" style="fill:#ccd6dd;fill-opacity:1;fill-rule:nonzero;stroke:none"/></g><g transform="translate(3,18)" id="g72"><path d="m 0,0 c -0.552,0 -1,0.447 -1,1 0,0.551 0.446,0.999 0.998,1 0.048,0 4.948,0.07 13.596,3.914 0.505,0.227 1.095,-0.002 1.32,-0.508 C 15.138,4.901 14.911,4.311 14.406,4.086 5.317,0.047 0.213,0 0,0" id="path74" style="fill:#99aab5;fill-opacity:1;fill-rule:nonzero;stroke:none"/></g><g transform="translate(35,18)" id="g76"><path d="m 0,0 c -0.213,0 -5.316,0.047 -14.406,4.086 -0.505,0.225 -0.732,0.815 -0.508,1.32 0.225,0.505 0.817,0.732 1.32,0.508 C -4.946,2.07 -0.046,2 0.003,2 0.554,1.997 1,1.548 0.999,0.997 0.997,0.446 0.551,0 0,0" id="path78" style="fill:#99aab5;fill-opacity:1;fill-rule:nonzero;stroke:none"/></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg enable-background="new 0 0 47.5 47.5" version="1.1" viewBox="0 0 47.5 47.5" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><defs><clipPath id="c"><path d="m0 38h38v-38h-38v38z"/></clipPath><clipPath id="b"><path d="m8.719 17c0-6.133 4.603-13 10.281-13 5.679 0 10.281 6.867 10.281 13s-4.602 8.923-10.281 8.923c-5.678 0-10.281-2.79-10.281-8.923"/></clipPath><clipPath id="a"><path d="m0 38h38v-38h-38v38z"/></clipPath></defs><g transform="matrix(1.25,0,0,-1.25,0,47.5)"><g clip-path="url(#c)"><g transform="translate(20,4)"><path d="m0 0c0-1.657-0.447-3-1-3-0.552 0-1 1.343-1 3s0.448 3 1 3c0.553 0 1-1.343 1-3" fill="#292f33"/></g><g transform="translate(26.753 35.753)"><path d="m0 0c-0.586 0.586-1.693 0.428-2.475-0.354-0.611-0.611-1.948-2.53-2.222-3.619-0.884 0.195-1.93 0.22-3.056 0.22-1.125 0-2.172-0.025-3.055-0.219-0.275 1.089-1.611 3.007-2.223 3.618-0.781 0.782-1.888 0.94-2.474 0.354s-0.428-1.693 0.353-2.475c0.511-0.51 1.937-1.529 3.027-2.011-0.82-0.533-1.315-1.451-1.315-3.032 0-3.589 2.546-7.312 5.687-7.312 3.142 0 5.688 3.723 5.688 7.312 0 1.581-0.496 2.499-1.316 3.032 1.091 0.482 2.517 1.5 3.027 2.011 0.782 0.782 0.94 1.889 0.354 2.475" fill="#292f33"/></g><g transform="translate(29.281 17)"><path d="m0 0c0-6.134-4.603-13-10.281-13s-10.281 6.866-10.281 13c0 6.133 4.603 8.923 10.281 8.923s10.281-2.79 10.281-8.923" fill="#292f33"/></g></g><g clip-path="url(#b)"><path d="m30 18h-22v4h22v-4z" fill="#ffcc4d"/><path d="m30 10h-22v4h22v-4z" fill="#ffcc4d"/><path d="m30 2h-22v4h22v-4z" fill="#ffcc4d"/><g transform="translate(19 23)"><path d="m0 0c0-2.647-7.858-10-12-10s-6 5.354-6 8 1.858 1.584 6 1.584c4.143 0 12 3.061 12 0.416" fill="#292f33"/></g><g transform="translate(19 23)"><path d="m0 0c0-2.647 7.857-10 12-10s6 5.354 6 8-1.857 1.584-6 1.584-12 3.061-12 0.416" fill="#292f33"/></g></g><g clip-path="url(#a)"><g transform="translate(19 23.495)"><path d="m0 0c0-2.647-7.858-8.584-12-8.584s-6 2.443-6 5.089 1.858 4.495 6 4.495c4.143 0 12 1.645 12-1" fill="#ccd6dd"/></g><g transform="translate(19 23.495)"><path d="m0 0c0-2.647 7.857-8.584 12-8.584s6 2.443 6 5.089-1.857 4.495-6 4.495-12 1.645-12-1" fill="#ccd6dd"/></g><g transform="translate(3,18)"><path d="m0 0c-0.552 0-1 0.447-1 1 0 0.551 0.446 0.999 0.998 1 0.048 0 4.948 0.07 13.596 3.914 0.505 0.227 1.095-2e-3 1.32-0.508 0.224-0.505-3e-3 -1.095-0.508-1.32-9.089-4.039-14.193-4.086-14.406-4.086" fill="#99aab5"/></g><g transform="translate(35,18)"><path d="m 0,0 c -0.213,0 -5.316,0.047 -14.406,4.086 -0.505,0.225 -0.732,0.815 -0.508,1.32 0.225,0.505 0.817,0.732 1.32,0.508 C -4.946,2.07 -0.046,2 0.003,2 0.554,1.997 1,1.548 0.999,0.997 0.997,0.446 0.551,0 0,0" fill="#99aab5"/></g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#77B255" d="M28.938 27.441c-2.554-.89-8.111-.429-9.938 1.331V17c0-.553-.447-1-1-1s-1 .447-1 1v11.772c-1.827-1.76-7.384-2.221-9.938-1.331-.741.259 5.264 8.749 9.507 4.507.168-.168.306-.33.431-.49V35c0 .553.447 1 1 1s1-.447 1-1v-3.542c.125.16.263.322.431.49 4.243 4.242 10.248-4.248 9.507-4.507z"/><path fill="#CCD6DD" d="M12.562 25.65c-.619-.266-1.107-.837-1.378-1.513l-1.266-3.306-3.258-1.393c-1.336-.574-1.876-1.922-1.304-3.259l1.362-3.181-1.364-3.269c-.541-1.35.15-2.868 1.5-3.408l3.272-1.281 1.449-3.384C12.148.32 13.496-.22 14.833.352l3.258 1.396L21.358.382c.675-.271 1.411-.276 2.03-.011.619.265 1.114.819 1.385 1.494l1.274 3.29 3.309 1.417c1.336.572 1.875 1.921 1.305 3.258l-1.451 3.384 1.365 3.267c.541 1.35-.15 2.866-1.5 3.407l-3.271 1.281-1.363 3.183c-.572 1.336-1.922 1.877-3.258 1.305l-3.308-1.417-3.267 1.364c-.676.271-1.427.311-2.046.046z"/><path fill="#E1E8ED" d="M29.356 6.572l-3.309-1.417-.055-.143c-1.565 1.337-5.215 4.354-5.215 4.354l.007.123C20.015 8.879 19.057 8.5 18 8.5V1.709L14.833.353c-1.337-.572-2.685-.032-3.258 1.304l-1.449 3.384-.061.024 4.753 4.754c-.814.813-1.318 1.938-1.318 3.181H6.717l-1.361 3.178c-.572 1.337-.032 2.686 1.304 3.259l3.258 1.394.002.006 4.496-5.142c.822 1.09 2.115 1.805 3.584 1.805h.005c.006 1.979.015 5.273.012 6.801l3.164 1.356c1.336.572 2.686.031 3.258-1.305l1.362-3.18-5.192-4.517c1.14-.816 1.89-2.145 1.89-3.654 0-.071-.018-.137-.021-.208 1.802.182 4.951.472 6.822.642l-.092-.22L30.66 9.83c.571-1.337.031-2.686-1.304-3.258z"/><circle fill="#F4900C" cx="18" cy="13" r="5"/></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
images/composer.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
images/h2.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

44
images/main.svg 100644

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
images/sct1.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
images/sct2.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
images/sct5.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
images/sprite.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
images/xbiff.gif 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

4
make_manpage.sh 100755
View File

@ -0,0 +1,4 @@
#!/bin/bash
# sed Removes trailing whitespace in <pre> elements
wget --timestamping "https://git.meli.delivery/meli/meli/raw/branch/master/"$1 -O - | mandoc -I os="rendered by mandoc" -Kutf-8 -Ofragment,toc,style="css/manpage.css",includes="#%I",man="#%N.%S" -Thtml | sed 's/\s*<\/pre/<\/pre/'

View File

@ -0,0 +1,31 @@
---
bees: What if bees lived in your socks?
ogDescription: Quick start tutorial and reference manual
---
# Quick start tutorial{#quick-start}
Follow the installation instructions in the [README](https://git.meli.delivery/meli/meli/src/branch/master/README.md).
Launch `meli`{.Nm .shake-little} with no arguments, and you will be asked if you want to create a sample configuration.
The [sample configuration](https://git.meli.delivery/meli/meli/src/branch/master/samples/sample-config.toml) (created by default in `~/.config/meli/config.toml`{.Pa}) includes comments with the basic settings required for setting up accounts allowing you to copy and edit right away. See [meli.conf(5)](#meli.conf) for the available configuration options.
The main screen when you launch `meli`{.Nm .shake-little} is the INBOX of the first account you have configured.
- With <kbd class="□">J</kbd> / <kbd class="□">K</kbd> you can select the next/previous folder. (To go to a specific one directly, press <kbd class="□">Space</kbd> and type the command `go n`{.Cm} where n is the number of the folder)
- With <kbd class="□">h</kbd> / <kbd class="□">l</kbd> you can select the next/previous account.
- Use the arrow keys to browse entries in the e-mail list of a folder. (Along with <kbd class="□ ▭">Home</kbd> / <kbd class="□ ▭ thin-kbd">End</kbd> / <kbd class="□ ▭">PgUp</kbd> / <kbd class="□ ▭">PgDn</kbd>)
- Use Enter to open an entry and <kbd class="□">i</kbd> to exit it.
- Use <kbd class="□">m</kbd> to start writing new e-mail. (or <kbd class="□">R</kbd> to reply to the entry you're currently viewing)
- Use the arrow keys to edit each field of the e-mail.
- Attachments can be added by pressing <kbd class="□">Space</kbd> and typing the command `add-attachment`{.Cm}&nbsp;`PATH`{.Pa} where `PATH`{.Pa} is the filesystem path of the attachment file.
- Edit the draft body at eny time by pressing <kbd class="□">e</kbd>
- Send your e-mail by pressing <kbd class="□">s</kbd>
- Discard or save your draft by pressing <kbd class="□">Space</kbd> and typing the command `close`{.Cm}
At any time, you can press <kbd class="□">?</kbd> to show a list of all available actions and shortcuts, along with every possible setting and command that your version supports.
Press <kbd class="□">T</kbd> to cycle between tabs or <kbd class="□">Alt</kbd> + <kbd class="□">1</kbd> ... <kbd class="□">9</kbd> to choose.
Press <kbd class="□">q</kbd> to exit.

58
pages/download.md 100644
View File

@ -0,0 +1,58 @@
---
showTitle: true
title: download
bees: What if you and bees had highly different taste in music?
---
* git <https://git.meli.delivery/meli/meli.git>
* read-only github mirror <https://github.com/meli/meli>
## install
<h4 id="debian">Debian</h4>
<p>Download an <code>amd64</code> <code>deb</code> package <a href="https://github.com/meli/meli/releases/">here</a>. Contributions for more packaging is welcome.</p>
<h4 id="binaries">static <code>amd64 linux</code> binary</h4>
<p><a href="https://github.com/meli/meli/releases/">https://github.com/meli/meli/releases/</a> </p>
<h4>other prebuilt binaries</h4>
<p>not available yet. Compile from <a href="https://git.meli.delivery/meli/meli.git">source</a> or install with <code>cargo</code>.</p>
### cargo{#cargo}
Note: `cargo` cannot distribute documentation. Install with `--features="cli-docs"` with `mandoc` or `man` in your system to use the command-line flags `--print-documentation [main config themes]` to print documentation in your terminal.
```sh
cargo install meli
```
## build
Build instructions can be found in the `README` file, but for convenience here's how to get it up and running:
```sh
git clone --depth=1 https://git.meli.delivery/meli/meli.git
cd meli
# print help
make
# try without installing:
# make meli
# ./target/release/meli
make PREFIX=$HOME/.local install
```
Read the [Quick start tutorial](documentation.html#quick-start). Documentation is located in the man pages and mirrored online [here](documentation.html).
Developed with focus on Linux for now, but if you get compilation errors or find bugs in your \*nix please report it in [meli-general](https://lists.meli.delivery) or [our issue tracker](https://git.meli.delivery/meli/meli/issues).
## contributing
There are no concrete contribution guidelines yet as the development workflow is still in its infancy. Mail your [patches](https://git-scm.com/docs/git-format-patch) to [meli-devel](https://lists.meli.delivery).
## bugs/support/feature requests
If you encounter a bug or a lack of features, you are encouraged to contact [meli-general](https://lists.meli.delivery). You don't need to subscribe to the mailing lists, but your message will have to be approved first.
Alternatively, you can post on our [issue tracker](https://git.meli.delivery/meli/meli/issues) <em>without registering</em> by sending an e-mail to `issues@` this address with the title of your report as the Subject and your text in the body. To hide your name and address while still being able to control your report, send your e-mail to `issues+anonymous@` instead.
By sending an e-mail to `issues@`, you will receive a special password you can use to control your report with a link to your issue. You will be automatically subscribed to replies to this issue. You can use the password to:
- close the issue `issues+${password}+close@`
- subscribe/unsubscribe to replies `issues+${password}+unsubscribe@`, `issues+${password}+subscribe@`
- reply `issues+${password}+reply@` (if your posting is anonymous, you will remain so)
If you encounter issues with `issues@` you can fall back to [meli-general](https://lists.meli.delivery) and report this as well.

18
pages/index.md 100644
View File

@ -0,0 +1,18 @@
---
html_title: meli terminal mail client
showTitle: false
mainClass: wrapper
bees: What if bees could travel through paintings?
screenshots:
- url : "/images/screenshots/conversations.webp"
desc: "Threads take one row by default."
- url : "/images/screenshots/conversations-view-open-thread.webp"
desc: "Viewing a thread."
- url : "/images/screenshots/threads.webp"
desc: "Compact view."
- url : "/images/screenshots/single-thread-view.webp"
desc: "Viewing a single thread. (UI not final)"
- url : "/images/screenshots/composing.svg"
desc: "Composing replies"
tag: alpha-0.6.0
---

View File

@ -0,0 +1,19 @@
---
title: mailing lists
bees: What if bees abstained from voting?
---
## contact/discuss/support
[mailing lists:](https://lists.meli.delivery)
* mailing list `<meli-general@at this domain>` [subscribe](https://lists.meli.delivery/mailman3/lists/meli-general.meli.delivery/)
* development list `<meli-devel@at this domain>` [subscribe](https://lists.meli.delivery/mailman3/lists/meli-devel.meli.delivery/)
* announcement list `<meli-announce@at this domain>` [subscribe](https://lists.meli.delivery/mailman3/lists/meli-announce.meli.delivery/)
[looking to contribute?](/download.html#contributing)
## archives
[https://lists.meli.delivery/archives/](https://lists.meli.delivery/archives/)
## IRC
there might also be people idling in `#meli` on freenode.

View File

@ -0,0 +1,26 @@
---
bees: What if bees built coral reefs?
screenshots:
- url : "/images/screenshots/light_theme.webp"
desc: "light theme"
- url : "/images/screenshots/composing.svg"
desc: "composing a mail"
- url : "/images/screenshots/add_contact_from_mail.webp"
desc: "adding contacts from received mail"
- url : "/images/screenshots/press_%3F_for_shortcuts.svg"
desc: "press ? for help with shortcuts"
- url : "/images/screenshots/command_auto_complete_and_history.svg"
desc: "enter commands with auto-completion"
- url : "/images/screenshots/gpg_signatures_verification.webp"
desc: "verification of gpg signatures"
- url : "/images/screenshots/recipient_auto_complete.webp"
desc: "autocompletion of email addresses"
- url : "/images/screenshots/conversations.webp"
desc: "Threads take one row by default."
- url : "/images/screenshots/conversations-view-open-thread.webp"
desc: "Viewing a thread."
- url : "/images/screenshots/threads.webp"
desc: "Compact view."
- url : "/images/screenshots/single-thread-view.webp"
desc: "Viewing a single thread. (UI not final)"
---

View File

@ -0,0 +1,133 @@
---
title: pre-alpha release
ogTitle: pre-alpha release
author: epilys
date: 2019-06-15 00:00:00
date_iso_8601: 2019-06-15T00:00:00+02:00
bees: What if bees are contagious?
left:
- url : "/images/sample-config.png"
desc: "Sample generated config on first run."
- url : "/images/thread-view.png"
desc: "Viewing a thread."
right:
- url : "/images/compact-listing.png"
desc: "Compact mail listing."
class: "dull-red bold"
- url : "/images/plain-listing.png"
desc: "Plain mail listing."
class: "cyan bold"
- url : "/images/threaded-listing.png"
desc: "Threaded mail listing."
class: "green bold"
- url : "/images/shortcuts-view.png"
desc: "View currently applicable shortcuts."
updates:
- date: 2019-07-08
content: Added mastodon account link, discussion link.
---
An early release with basic features and only Maildir support has been published in [meli's git repositories](https://git.meli.delivery/meli/meli/src/tag/pre-alpha-0.0). meli is a new experimental mail client for the terminal. It's a from-scratch implementation in order to experiment with ideas I had about a client's design.
Contributions and development will be hosted on [meli-devel@](https://lists.meli.delivery/mailman3/lists/meli-devel.meli.delivery/), as on the long run I would like to make mailing-list driven development comfortable and newbie-friendly by eliminating effort on the side of the contributor; the mailing list software should lift most of the burden by acting as a bug tracker, patch archive, maintainer tool, build tool. Note: no contribution guide has been drafted yet.
You can follow [meli-announce@](https://lists.meli.delivery/mailman3/lists/meli-announce.meli.delivery/), my mastodon account [\@epilys@chaos.social](https://chaos.social/@epilys) and the [RSS feed](/rss.xml) for updates.
General discussion, comments, etc is welcome on [meli-general@](https://lists.meli.delivery/mailman3/lists/meli-general.meli.delivery/).
meli aims to be a modal and hopefully a very configurable client. An API for plugins is in the current plans, allowing sufficient control of the client through scripting.
## what is usable now
While this stuff is on the roadmap, the pre-alpha supports Maildir folder structures, and three ways to render every folder: [one row per thread]{.dull-red .bold}, [one row per message]{.cyan .bold} and [one row per message]{.green .bold} but with the thread structure visible. Browsing a thread is done in the same view as reading the email, where you can simultaneously browse the thread and read an mail's content. Replying to an email can also come with the same thread view in order to have the whole conversation available while composing; composing is done in a different tab, so you can switch tabs anytime.
Commands can be executed via configurable shortcuts (bindings for the current view can be listed with the `?` shortcut) in `NORMAL` mode or commands in `EXECUTE` mode. Documentation is provided in a man page located in the root folder of the repository. You can view it with `man -l meli.1`{.shell} or rendered with `mandoc` on the [documentation page](/documentation.html).
## what basic functionality is coming later
For the moment there's no attachment ability in new e-mails, no IMAP support, no full text search ability or integration with notmuch. I suspect notmuch integration will coincide with the start of the API.
## what I am doing generally
MUAs are a lot of work, it turns out. I've been trying to scale it horizontally from the beginning, and I believe this helped as I was more focused on the overall architecture than individual functionalities. I have also tried to avoid adding dependencies when I could. I find it scary to install something and get hundreds of packages pulled.
I hope I can make it into a decent tool :)
## technical stuff
`meli` is written in Rust, with an Entity-Component-System design. The mail specific functions are done in a separate library crate, which means it can be reused for other mail applications.
### entity component system
A description of the ECS logic can be found here <https://en.wikipedia.org/wiki/Entity_component_system>
Every component of the application represents a single entity that can draw on the terminal, access user data or spawn processes. This is the entity & component part of the ECS architecture merged together.
All components implement the `Component`{.rust} trait:
```rust
pub trait Component {
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context);
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool;
fn is_dirty(&self) -> bool;
fn set_dirty(&mut self);
/* ... */
}
```
The program's data state is held in a System object called `Context`{.rust}. The `State`{.rust} object holds the necessary bits to run the basic event loop.
```rust
struct Context {
pub accounts: Vec<Account>,
pub mailbox_hashes: FnvHashMap<FolderHash, usize>,
pub settings: Settings,
pub runtime_settings: Settings,
/// Areas of the screen that must be redrawn in the next render
pub dirty_areas: VecDeque<Area>,
/// Events queue that components send back to the state
pub replies: VecDeque<UIEvent>,
sender: Sender<ThreadEvent>,
receiver: Receiver<ThreadEvent>,
input: InputHandler,
pub temp_files: Vec<File>,
}
struct State {
cols: usize,
rows: usize,
grid: CellBuffer, /* The terminal as a grid */
stdout: Option<StateStdout>,
child: Option<ForkType>,
pub mode: UIMode, /* Normal, Input, Execute input, Fork.. */
components: Vec<Box<Component>>, /* UI components */
pub context: Context,
threads: FnvHashMap<thread::ThreadId, (chan::Sender<bool>, thread::JoinHandle<()>)>,
work_controller: WorkController, /* async jobs */
}
```
### drawing output
An event loop looks roughly like this:
- see if `Context`{.rust} contains events to be received. These events are added by Components in previous loops.
- if any event existed, the grid might be modified. So redraw all dirty bits of the terminal grid.
- block on multiple writers-single reader channel that receives from the input thread, the mail update polling threads, timers, and anything else that accesses `Context.sender`{.rust} field.
- `State`{.rust} passes down the events by calling `component.process_event(&mut event, &mut self.context)`{.rust}. Components recursively pass the event down to their children.
UI updates are supposed to be incremental for speed. Single envelope updates should only cause the minimally required UI updates.
When drawing, Components update the grid and push the area coordinates of their updates to `Context`{.rust}. When State finally redraws in the next event loop, it does a horizontal sweep in all the dirty areas to avoid redrawing common parts. Areas are sorted by `x` coordinate and common segments of all dirty areas are drawn once.
### data handling
To represent relationships between different objects without references, vector indexes and hashmap keys are used. This way most data reading or modification is done inside the `Context`{.rust} object. Caution must be exercised to keep all these indirect references up to date when something is modified or deleted.
A great difficulty I face in debugging is visualising all these connections. I've started a library to provide access to `Debug`{.rust} implementations for gdb's pretty printing python API but I haven't reached any result yet.
Mail parsing is done asynchronously in separate threads. Mail backends such as IMAP, Maildir have to implement a `Backend`{.rust} trait. So far I've used the trait only with Maildir, which means it was written with its needs and abilities in mind. If all goes well, IMAP should start in the nearish future.
Discussions:
- [*lobste.rs*](https://lobste.rs/s/fqcpxq/meli_new_mail_client_for_terminal_pre)
- [*reddit/r/rust*](https://www.reddit.com/r/rust/comments/ca9k75/meli_a_new_mail_client_for_the_terminal_prealpha/)
- [*hackernews*](https://news.ycombinator.com/item?id=20378657)

View File

@ -0,0 +1,42 @@
---
title: v0.3.0 release - Now with IMAP, xbiff support
ogTitle: v0.3.0 release - Now with IMAP, xbiff support
author: epilys
date: 2019-09-16 00:00:00
date_iso_8601: 2019-09-16T00:00:00+02:00
bees: What if bees seized the means of reduction?
left:
- url : "/images/screenshots/conversations.webp"
desc: ""
- url : "/images/screenshots/conversations-view-open-thread.webp"
desc: "Viewing a thread."
right:
- url : "/images/xbiff.gif"
desc: "co-operation with modern tools is a priority"
---
[Get meli v0.3.0](https://git.meli.delivery/meli/meli/src/tag/pre-alpha-0.3.0) meli is now a `make && make PREFIX=$HOME/.local install` away!
\
\
![release bee](/images/0-3-0-bee.png){.float_left_img}
## changelog:
- IMAP support. Unpolished and experimental.
- [xbiff](https://linux.die.net/man/1/xbiff) support
- added portable Makefile for installation
- added manual page for the configuration file [meli.conf(5)](/documentation.html#meli.conf)
- various configuration changes can be seen in meli.conf(5)
- add conversations thread mailing view: a one entry per thread listing, but entries are less compact; they take 3 rows. Pager opens on the right. Intended for big terminals.
- added folder operations (create, delete, rename)
- added special use semantics for mailboxes: you can specify which mailboxes are special, eg specify `INBOX/Sent` as the `Sent` folder, `INBOX/Drafts` as `Drafts`, etc. This is optional as it in most cases it can be inferred by the names.
- add folder subscriptions: don't load all folders on startup, only the ones the user has specified
## status
As before, this is a rough around the edges release. I'm working on a lot of stuff simultaneously and I can't stop and improve something. Please understand.
Consider trying this release and file bug reports for any problems or suggestions you have. Documentation can be found in the installed manpages, `man` [meli](/documentation.html#meli) and `man` [meli.conf](/documentation.html#meli.conf). You will unfortunately have to sign up in meli's [gitea instance](https://git.meli.delivery/meli/meli/) to file bugs though. I am considering writing a bot to transfer mails from a bug report mailing list to gitea via its API.
You're welcome to reach me via [Mastodon \@epilys@chaos.social](https://chaos.social/@epilys) or if you're feeling extremely enthusiastic, the [meli-general@](https://lists.meli.delivery/mailman3/lists/meli-general.meli.delivery/) mailing list.
You can follow [meli-announce@](https://lists.meli.delivery/mailman3/lists/meli-announce.meli.delivery/), my mastodon account [\@epilys@chaos.social](https://chaos.social/@epilys) and the [RSS feed](/rss.xml) for updates.

View File

@ -0,0 +1,454 @@
---
title: making a quick and dirty terminal emulator
ogTitle: making a quick and dirty terminal emulator
author: epilys
date: 2019-10-25 00:00:00
date_iso_8601: 2019-10-25T00:00:00+02:00
bees: What if bees were made of bigger bees but smaller?
---
<figure>
<img width="100%" height="auto" src="/images/hark_canine.png" alt="Nested meli instances" />
<figcaption>I gave up at 15 levels deep (though I had to stretch the height a lot to view them all)</figcaption>
</figure>
## Background
In order to be able to compose e-mail within meli and avoid writing an editor, making an embed terminal was obviously my only choice. I didn't bother to look if there are already libraries in Rust for this because as always my prime motivator is figuring things out, for fun.
If you have ever executed `tty` before you'd probably see a response like `/dev/pts/16`. `pts` stands for pseudoterminal slave: the process (such as a shell) running inside it thinks it's speaking directly to an actual terminal, i.e. the virtual console you see when you <kbd class="□">Ctrl</kbd> <kbd class="□">Alt</kbd> <kbd class="□">F1</kbd> etc. Terminal emulators such as `xterm` create pseudoterminals and communicate with them by reading and writing to the pts device and the pseudoterminal reads and writes to `/dev/ptmx`. The kernel handles the pairing of I/O between each master/slave. You'll read how to create one below, but for more information read `pty(7)` on Linux, `pty(4)` on *BSDs.
> A pseudoterminal (sometimes abbreviated "pty") is a pair of virtual
> character devices that provide a bidirectional communication channel. One
> end of the channel is called the master; the other end is called the slave.
> The slave end of the pseudoterminal provides an interface that behaves
> exactly like a classical terminal. A process that expects to be connected to
> a terminal, can open the slave end of a pseudoterminal and then be driven
> by a program that has opened the master end. Anything that is written on the
> master end is provided to the process on the slave end as though it was
> input typed on a terminal. For example, writing the interrupt character
> (usually control-C) to the master device would cause an interrupt signal
> (SIGINT) to be generated for the foreground process group that is connected
> to the slave. Conversely, anything that is written to the slave end of
> the pseudoterminal can be read by the process that is connected to the master
> end. Pseudoterminals are used by applications such as network login
> services (ssh(1), rlogin(1), telnet(1)), terminal emulators such as xterm(1),
> script(1), screen(1), tmux(1), unbuffer(1), and expect(1).
## First steps
Let's begin with creating the pty:
```rust
use crate::terminal::position::Area;
use nix::fcntl::{open, OFlag};
use nix::{ioctl_none_bad, ioctl_write_ptr_bad};
use nix::pty::{grantpt, posix_openpt, ptsname, unlockpt, Winsize};
use nix::sys::stat::Mode;
use libc::TIOCSCTTY;
// ioctl request code to set window size of pty:
use libc::TIOCSWINSZ;
use std::path::Path;
use std::process::{Command, Stdio};
use std::os::unix::io::{FromRawFd, IntoRawFd};
// nix macro that generates an ioctl call to set window size of pty:
ioctl_write_ptr_bad!(set_window_size, TIOCSWINSZ, Winsize);
// request to "Make the given terminal the controlling terminal of the calling process"
ioctl_none_bad!(set_controlling_terminal, TIOCSCTTY);
pub fn create_pty() -> nix::Result<()> {
/* Create a new master */
let master_fd = posix_openpt(OFlag::O_RDWR)?;
/* For some reason, you have to give permission to the master to have a
* pty. What is it good for otherwise? */
grantpt(&master_fd)?;
unlockpt(&master_fd)?;
/* Get the path of the slave */
let slave_name = unsafe { ptsname(&master_fd) }?;
/* Try to open the slave */
let _slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, Mode::empty())?;
/* Launch our child process. The main application loop can inspect and then
pass the stdin data to it. */
let _child_pid = match fork() {
Ok(ForkResult::Child) => {
/* Open slave end for pseudoterminal */
let slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, stat::Mode::empty())?;
// assign stdin, stdout, stderr to the tty
dup2(slave_fd, STDIN_FILENO).unwrap();
dup2(slave_fd, STDOUT_FILENO).unwrap();
dup2(slave_fd, STDERR_FILENO).unwrap();
/* Become session leader */
nix::unistd::setsid().unwrap();
unsafe { set_controlling_terminal(slave_fd) }.unwrap();
nix::unistd::execv(
&CString::new("/usr/bin/vim").unwrap(),
Vec::new(),
).unwrap();
/* This path shouldn't be executed. */
std::process::exit(-1);
}
Ok(ForkResult::Parent { child }) => child,
Err(e) => panic!(e),
};
/* Continue dealing with the pty in a thread so that the main application doesn't lock up */
std::thread::Builder::new()
.spawn(move || {
let winsize = Winsize {
ws_row: 25,
ws_col: 80,
ws_xpixel: 0,
ws_ypixel: 0,
};
let master_fd = master_fd.into_raw_fd();
/* Tell the master the size of the terminal */
unsafe { set_window_size(master_fd, &winsize).unwrap() };
let master_file = unsafe { std::fs::File::from_raw_fd(master_fd) };
/* start the pty liaison */
liaison(master_file);
})
.unwrap();
Ok(())
}
```
So far graphics are not in the picture (heh). To draw directly on the screen we can print the bytes we read from the master without doing any sort of work in-between:
```rust
fn liaison(pty_fd: std::fs::File) {
let stdout = std::io::stdout();
let mut lock = stdout.lock();
let mut bytes_iter = pty_fd.bytes();
while let Some(Ok(byte)) = bytes_iter.next() {
lock.write_all(&[byte]).unwrap();
}
}
```
## Embedding graphics
A quick explanation on how meli graphics work: There's a two dimensional grid representing the state of the terminal at the current moment. Its elements are of type `Cell`:
```rust
struct Cell {
ch: char,
fg: Color,
bg: Color,
attrs: Attr,
}
```
To cache stuff I've made some UI components draw their stuff into their own grids and whenever I have to redraw, they copy the cache instead of recomputing data. To actually show changes on the screen each component pushes the area of the grid they have changed into the app state, and whenever it's time to draw the app displays only the dirty areas. On resize all of the components are marked dirty and redraw everything on the newly resized grid.
The embedded process can thus draw its output on such a grid and we can then draw it like a regular UI widget.
### How the terminal handles output
For terminal UI apps we're interested in the Alternative screen buffer mode. In this mode the application is responsible for handling the cursor. There is no scrollback, to emulate scrolling the app has to redraw the screen entirely or use a special scrolling functionality that is out of scope for this post.
To handle colours, cursor style changes, cursor position changes, the application sends *control sequences* to the terminal, which are sequences of bytes with designated prefixes and suffixes that correspond to a command. `xterm` control sequences are not standardised, but [here is one list](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Functions-using-CSI-_-ordered-by-the-final-character_s_). A quick summary with examples can be found in the [Wikipedia Article](https://en.wikipedia.org/wiki/ANSI_escape_code).
All sequences start with the Escape character, `0x1b`, and are sorted in separate categories. The basic one is `CSI` or *Command Sequence Introducer*, which is Escape followed by `[`.
Since we're pretending to be a terminal, we will encode the code sequence input's state in a state machine:
```rust
pub enum State {
Normal, // Waiting for any kind of byte
ExpectingControlChar, // We just got an ESC and expect a control sequence
Csi, // ESC [ Control Sequence Introducer
/* Multiparameter sequences are of the form KIND P_1 ; P_2 ; ... TERMINATION */
Csi1(Vec<u8>), // CSI with one buffer (CSI <num>) waiting for new buffer digits, a second buffer or a termination character
Csi2(Vec<u8>, Vec<u8>), // CSI with two buffers (CSI <num> ; <num>) as above
Csi3(Vec<u8>, Vec<u8>, Vec<u8>), // CSI with three buffers
CsiQ(Vec<u8>), // CSI followed by '?'
Osc1(Vec<u8>), // ESC ] Operating System Command
Osc2(Vec<u8>, Vec<u8>),
}
```
The embed grid will include all the simulated terminal's state:
```rust
pub struct EmbedGrid {
/*
1 2 ..
┏━━━┯━━━━━━━┅┅ x axis
1 ┃1,1│
┠───┼┈┈
2 ┃ ┊
.. ┃
y axis ┇
*/
cursor: (usize, usize), // xterm cursor starts from (1, 1), but ours from (0, 0)
pub grid: CellBuffer,
pub state: State,
pub stdin: std::fs::File,
// Pid of the embed process
pub child_pid: nix::unistd::Pid,
// (width, height)
pub terminal_size: (usize, usize),
// Current colors
fg_color: Color,
bg_color: Color,
show_cursor: bool,
/* And others */
..
}
```
And here's the methods to control the terminal:
```rust
impl EmbedGrid {
pub fn set_terminal_size(&mut self, new_val: (usize, usize)) {
if new_val == self.terminal_size {
return;
}
self.terminal_size = new_val;
self.grid.resize(new_val.0, new_val.1, Cell::default());
self.grid.clear(Cell::default());
self.cursor = (0, 0);
let winsize = Winsize {
ws_row: <u16>::try_from(new_val.1).unwrap(),
ws_col: <u16>::try_from(new_val.0).unwrap(),
ws_xpixel: 0,
ws_ypixel: 0,
};
let master_fd = self.stdin.as_raw_fd();
/* This is the macrogenerated function we defined earlier, which calls
ioctl underneath */
unsafe { set_window_size(master_fd, &winsize).unwrap() };
/* SIGWINCH informs the process the tty size has changed. TUI apps must
handle this signal */
nix::sys::signal::kill(self.child_pid, nix::sys::signal::SIGWINCH).unwrap();
}
pub fn wake_up(&self) {
nix::sys::signal::kill(self.child_pid, nix::sys::signal::SIGCONT).unwrap();
}
pub fn stop(&self) {
/* we can emulate Ctrl-z and suspend the child process from meli */
nix::sys::signal::kill(self.child_pid, nix::sys::signal::SIGSTOP).unwrap();
}
pub fn process_byte(&mut self, byte: u8);
}
```
In the `process_byte` method we take input from the child process and we perform actions depending on the control sequence state:
- if it's `Normal` and we get a byte that does not start a sequence, we output it on the grid.
- if the state is in a sequence and we get a valid termination byte, we perform the sequence's action
- if the state is in a sequence and we get a valid continuation byte, we update the state
- else, the child process sent malformed output or we haven't implemented some sequence correctly (at this stage, probably the latter)
```rust
pub fn process_byte(&mut self, byte: u8) {
let EmbedGrid {
ref mut cursor,
ref terminal_size,
ref mut grid,
ref mut state,
ref mut stdin,
ref mut fg_color,
ref mut bg_color,
child_pid: _,
..
} = self;
macro_rules! increase_cursor_x {
() => {
if cursor.0 + 1 < terminal_size.0 {
cursor.0 += 1;
}
};
}
macro_rules! cursor_x {
() => {{
if cursor.0 >= terminal_size.0 {
cursor.0 = terminal_size.0.saturating_sub(1);
}
cursor.0
}};
}
macro_rules! cursor_y {
() => {
std::cmp::min(
cursor.1 + scroll_region.top,
terminal_size.1.saturating_sub(1),
)
};
}
macro_rules! cursor_val {
() => {
(cursor_x!(), cursor_y!())
};
}
let mut state = state;
match (byte, &mut state) {
(b'\x1b', State::Normal) => {
*state = State::ExpectingControlChar;
}
(b']', State::ExpectingControlChar) => {
let buf1 = Vec::new();
*state = State::Osc1(buf1);
}
(b'[', State::ExpectingControlChar) => {
*state = State::Csi;
}
/* 8<... */
(b'H', State::Csi) => {
/* move cursor to (1,1) */
*cursor = (0, 0);
*state = State::Normal;
}
/* 8<... */
(b'\r', State::Normal) => {
// carriage return x-> 0
cursor.0 = 0;
}
(b'\n', State::Normal) => {
// newline y -> y + 1
if cursor.1 + 1 < terminal_size.1 {
cursor.1 += 1;
}
}
/* replaced the actual ^G character here with '^' + 'G' for clarity: */
(b'^G', State::Normal) => {
// Visual bell ^G, ignoring
}
(0x08, State::Normal) => {
/* Backspace */
// x -> x - 1
if cursor.0 > 0 {
cursor.0 -= 1;
}
}
(c, State::Normal) => {
/* Character to be printed. */
/* We're UTF-8 bound, so check if byte starts a multi-byte
codepoint and keep state on this in order to get the complete
char, which will be 1-4 bytes long.
Check UTF-8 spec to see how it's defined.
*/
/* ...codepoint checks ...8< */
grid[cursor_val!()].set_ch(c);
grid[cursor_val!()].set_fg(*fg_color);
grid[cursor_val!()].set_bg(*bg_color);
increase_cursor_x!();
}
/* other various sequences: */
(b'H', State::Csi2(ref y, ref x)) => {
// Set Cursor Position [row;column] (default = [1,1])
let orig_x = unsafe { std::str::from_utf8_unchecked(x) }
.parse::<usize>()
.unwrap_or(1);
let orig_y = unsafe { std::str::from_utf8_unchecked(y) }
.parse::<usize>()
.unwrap_or(1);
if orig_x - 1 <= terminal_size.0 && orig_y - 1 <= terminal_size.1 {
cursor.0 = orig_x - 1;
cursor.1 = orig_y - 1;
} else {
eprintln!(
"[error] terminal_size = {:?}, cursor = {:?} but cursor set to [{},{}]",
terminal_size, cursor, orig_x, orig_y
);
}
*state = State::Normal;
}
(b'm', State::Csi1(ref buf1)) => {
// Set color
match buf1.as_slice() {
/* See next sequence for 38 and 48 special meanings */
b"30" => *fg_color = Color::Black,
b"31" => *fg_color = Color::Red,
b"32" => *fg_color = Color::Green,
b"33" => *fg_color = Color::Yellow,
b"34" => *fg_color = Color::Blue,
b"35" => *fg_color = Color::Magenta,
b"36" => *fg_color = Color::Cyan,
b"37" => *fg_color = Color::White,
b"39" => *fg_color = Color::Default,
b"40" => *bg_color = Color::Black,
b"41" => *bg_color = Color::Red,
b"42" => *bg_color = Color::Green,
b"43" => *bg_color = Color::Yellow,
b"44" => *bg_color = Color::Blue,
b"45" => *bg_color = Color::Magenta,
b"46" => *bg_color = Color::Cyan,
b"47" => *bg_color = Color::White,
b"49" => *bg_color = Color::Default,
_ => {}
}
grid[cursor_val!()].set_fg(*fg_color);
grid[cursor_val!()].set_bg(*bg_color);
*state = State::Normal;
}
(b'm', State::Csi3(ref buf1, ref buf2, ref buf3)) if buf1 == b"38" && buf2 == b"5" => {
/* ESC [ m 38 ; 5 ; fg_color_byte m */
/* Set only foreground color */
*fg_color = if let Ok(byte) =
u8::from_str_radix(unsafe { std::str::from_utf8_unchecked(buf3) }, 10)
{
Color::Byte(byte)
} else {
Color::Default
};
grid[cursor_val!()].set_fg(*fg_color);
*state = State::Normal;
}
(b'm', State::Csi3(ref buf1, ref buf2, ref buf3)) if buf1 == b"48" && buf2 == b"5" => {
/* ESC [ m 48 ; 5 ; fg_color_byte m */
/* Set only background color */
*bg_color = if let Ok(byte) =
u8::from_str_radix(unsafe { std::str::from_utf8_unchecked(buf3) }, 10)
{
Color::Byte(byte)
} else {
Color::Default
};
grid[cursor_val!()].set_bg(*bg_color);
*state = State::Normal;
}
(b'D', State::Csi1(buf)) => {
// ESC[{buf}D CSI Cursor Backward {buf} Times
let offset = unsafe { std::str::from_utf8_unchecked(buf) }
.parse::<usize>()
.unwrap();
cursor.0 = cursor.0.saturating_sub(offset);
*state = State::Normal;
}
/* and others */
}
}
```
A bit of UI glue code later:
<video src="/images/2019-11-04_13.33.15.mp4" controls loop="true" width="100%">

View File

@ -0,0 +1,145 @@
---
title: meli mail client - alpha release 0.4.1
ogTitle: meli mail client - alpha release 0.4.1
author: epilys
date: 2019-12-09 00:00:00
date_iso_8601: 2019-12-09T00:00:00+02:00
bees: What if bees could see the abyss of deep knees in a sea
left:
right:
updates:
---
>> **update**: _0.4.1 is supported for rust >= 1.39_ Checkout current master or latest release tag for bug fixes since 0.4.1.
## Summary
- New mail stores available: **IMAP**, **notmuch** join **Maildir** and **mbox**. _JMAP_ is partially supported but not shipped with the master branch release.
- **Tagging** (on IMAP & notmuch) with
- custom colours
- hiding unwanted tags
- use as search keyword
- **Embed your editor** in the composing tab without ever leaving <code class="Nm">meli</code>. The editor runs in an embedded terminal emulator.
- **vCard support**, read-only from local storage.
- **Search**
- Full text search if _sqlite3_ cache selected
- _SEARCH_ in _IMAP_ without a cache
- _notmuch queries_ in _notmuch_ without a cache
- **GPG signatures**, signing and verifying
- **mailcap** support
- **format=flowed** support
and other smaller additions. Consult the [manpages](/documentation.html) for up-to-date information.
[Download](/download.html)
<figure><img src="/images/posts/2019-12-09-alpha-release/tags.png" style="height: min-content;width: min-content;margin: auto;" /></figure>
## stability
I use <code class="Nm">meli</code> as my main client and though at times buggy, it is mostly stable enough to be usable. Data is treated immutably everywhere _except_ for when you explicitly ask for mutation, meaning I don't think data corruption is generally possible. I'd appreciate bug reports at this stage in order to start polishing it for a proper release.
## IMAP, notmuch and... JMAP?
>> _See example configuration files in [meli.conf.5](/documentation.html#meli.conf.5)_
_IMAP_ accounts are retrieved on startup without any local caching. It is easy to implement though and I expect to do it soonish.
_notmuch_ accounts don't support new mail notifications yet. I have to check if I should use _inotify_ just like in _Maildir_ or poll the database's _mtime_. notmuch search queries are passed to _libnotmuch_ unchanged, though the app's search syntax is quite similar.
_JMAP_ is at an early stage still and unless you are a dev in pertinent projects or just really want to try it you shouldn't care about it yet. I've written code using [jmap-proxy](https://github.com/jmapio/jmap-perl) for _IMAP_ written in _Perl_. Authentication is still an unclear subject in _JMAP_ and I haven't a way to implement how fastmail, the company behind _JMAP_, does it without an account.
_JMAP_ translates really well to Rust thanks to _serde\_json_. By modeling _JMAP Objects_ and methods as traits we can have some type safety in our queries:
```rust
trait Object {
const NAME: &'static str;
}
trait Response<OBJ: Object> {
const NAME: &'static str;
}
trait Method<OBJ: Object>: Serialize {
const NAME: &'static str;
}
struct Request {
using: &'static [&'static str],
/* Why is this Value instead of Box<dyn Method<_>>? The Method trait cannot
be made into a Trait object because its serialize() will be generic.
Bummer! */
method_calls: Vec<serde_json::Value>,
#[serde(skip)]
request_no: Arc<Mutex<usize>>,
}
#[serde(rename_all = "camelCase")]
struct Get<OBJ: Object>
where
OBJ: std::fmt::Debug + Serialize,
{
account_id: String,
#[serde(flatten)]
ids: Option<JmapArgument<Vec<String>>>,
properties: Option<Vec<String>>,
#[serde(skip)]
_ph: PhantomData<*const OBJ>,
}
#[serde(rename_all = "camelCase")]
struct EmailGet {
#[serde(flatten)]
get_call: Get<EmailObject>,
body_properties: Vec<String>,
fetch_text_body_values: bool,
fetch_html_body_values: bool,
fetch_all_body_values: bool,
max_body_value_bytes: u64,
}
impl Method<EmailObject> for EmailGet {
const NAME: &'static str = "Email/get";
}
```
One of _JMAP_'s features is the ability to reference the results of previous calls in the same request, thus preventing the need for round-trips:
```rust
#[serde(rename_all = "camelCase")]
enum JmapArgument<T> {
Value(T),
ResultReference {
result_of: String,
name: String,
path: String,
},
}
```
## vCard
vCard is [haphazardly](https://git.meli.delivery/meli/meli/src/branch/master/melib/src/addressbook/vcard.rs#L75) parsed and available along with <code class="Nm">meli</code> contacts. They are read-only for now, until a more standard-compliant parser and serializer is written.
<figure><img src="/images/posts/2019-12-09-alpha-release/contacts.png" style="height: min-content;width: min-content;margin: auto;" /></figure>
## sqlite3
sqlite3 searching uses a simple query language based on the Gmail webclient one:
> ((from:unrealistic and (to:complex or not "query")) or flags:seen,draft)
You can also explore your data with SQL by loading the database (_$XDG_DATA\_HOME/meli/_) with the sqlite3 cli tool.
_IMAP_ searches are converted from this language to _SEARCH_ queries. _notmuch_ queries are not tampered with at all.
## quick unsubscribe
<figure><img src="/images/posts/2019-12-09-alpha-release/list_actions.png" style="height: min-content;width: min-content;margin: auto;"/></figure>
If a newsletter has a _List-Unsubscribe_ header, <code class="Nm">meli</code> can send an unsubscribe request with the command _list-unsubscribe_. Other _List-*_ headers are also usable.
## mailcap
You can now open attachments using mailcap files. You can still open them with _xdg-open_ as well.
## account info
View supported mailstore features in the _status_ tab:
<figure><img src="/images/posts/2019-12-09-alpha-release/imap_status.png" style="height: min-content;width: min-content;margin: auto;" /></figure>
<figure><img src="/images/posts/2019-12-09-alpha-release/maildir_status.png" style="height: min-content;width: min-content;margin: auto;"/></figure>
## vim-like motions
Prepend any move motion with a number _n_ to repeat it _n_ times.

View File

@ -0,0 +1,180 @@
---
title: v0.6.0 alpha release
ogTitle: v0.6.0 alpha release
ogImage: /images/posts/v0.6.0.png
author: epilys
date: 2020-07-29 00:00:00
date_iso_8601: 2020-07-29T00:00:00+02:00
bees: What if bees flew the coop?
left:
right:
---
A new alpha version is up for test/review. It's starting to look like a real client! [Get it here](/download.html#install). Some highlights are:
- Support for async IO using the `smol` runtime. `IMAP` backend is now async.
- imap: `add server_password_command`
- add optional SMTP client. Instead of using an external command (I was using `msmtp` for example) meli can connect to an SMTP server by itself. See documentation for `send_mail` option.
- Custom themes
## Online demo
I managed to compile meli to WebAssembly, and made [an online demo](https://meli.delivery/wasm2.html) so that you can get a feel for it without having to download/build it first. It's not perfect, but it works.
![main screen screenshot](/images/posts/v0.6.0.png)
## Themes
### what
meli comes with two themes, dark (the default) and light. Here's how a theme is defined:
```sh
[terminal.themes.watermelon]
"theme_default" = { fg = "#F50431", bg = "#FFD5FD", attrs = "Default" }
"widgets.list.header" = { fg = "#FFD5FD", bg = "#F50431", attrs = "Bold" }
"mail.listing.attachment_flag" = { fg = "LightSlateGrey", bg = "theme_default", attrs = "theme_default" }
"mail.listing.compact.even" = { fg = "White", bg = "#6CA94A", attrs = "Bold" }
"mail.listing.compact.highlighted" = { fg = "#157241", bg = "#f74b41", attrs = "theme_default" }
...
```
etc.
You can also define color aliases:
```sh
[terminal.themes."hunter2"]
color_aliases= { "Jebediah" = "#b4da55" }
"mail.listing.tag_default" = { fg = "$Jebediah" }
...
```
There's also a currently undocumented feature if built with `pcre2`: theme formatting of three places in the UI. Here's an example configuration;
```toml
[terminal.themes.win95.text_format_regexps]
"listing.from" = { "\\<[^\\>]*\\>(?:(?:\\s*$)|(?=,))" = { attrs = "Italics" } }
[terminal.themes.win95.text_format_regexps."listing.subject"]
"^\\[Lobsters\\]" = { attrs = "Bold", fg = "White", bg = "#AA120C", priority = 0}
"^\\[(?:(?:[^\\]]*/[^\\]]*)|(?:[Gg]it[Hh]ub))\\]" = { attrs = "Bold", fg = "White", bg = "#24292E", priority = 0}
"^\\[[^\\]]*\\]" = { attrs = "Bold", fg = "White", bg = "#5A828E", priority = 1}
[terminal.themes.win95.text_format_regexps."pager.envelope.body"]
# "^[^\\n]*(?=\\n>)" = { attrs = "Italics", multi_line = true }
"^>.*$" = { attrs = "Italics" }
"\\d+\\s?(?:(?:[KkMmTtGg]?[Bb])|(?:[KkMmTtGg][Bb]?)(?=\\s))" = { attrs = "Bold | Underline" }
```
### where
Custom themes can be defined as lists of key-values in the configuration files:
- `$XDG_CONFIG_HOME/meli/config.toml`
- `$XDG_CONFIG_HOME/meli/themes/*.toml`
The application theme is then defined in the configuration as follows:
```sh
[terminal]
theme = "dark"
```
### how
You can create a theme template with a command line flag:
```sh
meli print-default-theme > ~/.config/meli/themes/new_theme.toml
```
Sample themes can be found in the `samples/` directory in the source repository. Detailed documentation can be found in `meli-themes(5)` which is also available [online](/documentation.html)
_sidenote: I couldn't get mandoc to generate large (i.e. longer than a page) tables. There is a GNU mdoc extension for this but it's not supported. Bummer_
![watermelon theme](/images/posts/c8d041b1f73642bb_watermelon_theme.png)
## Other subcommands
```sh
SUBCOMMANDS:
create-config create a sample configuration file with available configuration options. If PATH is not
specified, meli will try to create it in $XDG_CONFIG_HOME/meli/config.toml
test-config test a configuration file for syntax issues or missing options
man print documentation page and exit (Piping to a pager is recommended.) [aliases: docs]
help Prints this message or the help of the given subcommand(s)
print-default-theme print default theme in full to stdout and exit
print-loaded-themes print loaded themes in full to stdout and exit
view View mail from input file
```
## Usability improvements
- Set **default filter** globally or per-mailbox e.g. show only unseen e-mail (_virtual mailboxes_ coming soon). This is done on the UI and not in the backend, so specifying a filter won't for example make less IMAP requests. This will be supported in the future.
```sh
[listing]
filter = "not flags:seen" # show only unseen messages globally
# or
[accounts."personal account".mailboxes]
"INBOX" = { listing.filter = "not flags:seen" } # override global settings for this mailbox
```
- Oh, and **override** any setting that makes sense per mailbox or per account. You can for example use different sending mail options for each account, or different shortcuts for some mailboxes.
- **Search** in pagers, and the shortcut panel with a simple [KMP](https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm) implementation
- **Autoload** mailbox option - don't load big mailboxes on startup till you request them
- **Create/delete** mailbox, {un,}subscribe mailbox
- Set **default headers**
- Manual check for **new mail** (default key <kbd class="□">F5</kbd>). IMAP checks server, maildir can be configured to run a command (setting `refresh_command`)
- Primitive fs autocomplete for commands, till a proper parser with states is written
- Custom date format strings
- `$NO_COLOR` **disable colors** application-wide conforming to [https://no-color.org](https://no-color.org)
- `libnotmuch` is now loaded **dynamically**. It's included in the default build configuration.
- Display `text/html` attachments if the `text/plain` alternative is empty. (setting: `auto_choose_multipart_alternative`)
## Distribution and building
- **Makefile** has been improved:
```sh
/path/to/meli % make help
For a quick start, build and install locally:
PREFIX=~/.local make install
Available subcommands:
- meli (builds meli with optimizations in $CARGO_TARGET_DIR)
- install (installs binary in $BINDIR and documentation to $MANDIR)
- uninstall
Secondary subcommands:
- clean (cleans build artifacts)
- check-deps (checks dependencies)
- install-bin (installs binary to $BINDIR)
- install-doc (installs manpages to $MANDIR)
- help (prints this information)
- dist (creates release tarball named meli-0.5.1.tar.gz in this directory)
- deb-dist (builds debian package in the parent directory)
- distclean (cleans distribution build artifacts)
ENVIRONMENT variables of interest:
* PREFIX = /usr/local
* MELI_FEATURES = unset
* BINDIR = /usr/local/bin
* MANDIR = /usr/local/share/man
* MANPATH = unset
* output of manpath(1) = /home/epilys/.local/share/man:/usr/share/man:/usr/local/man:/usr/local/share/man
* NO_MAN unset
* NO_COLOR unset
```
### binaries and debian package
- [Debian packaging](https://github.com/meli/meli/releases)
- [Binary distrib](https://github.com/meli/meli/releases)
### available in crates.io
[https://crates.io/crates/meli](https://crates.io/crates/meli)
## What's next
- async JMAP
- [NNTP](https://git.meli.delivery/meli/meli/issues/54), [RSS](https://git.meli.delivery/meli/meli/issues/55) backends
- mail storage sync/conversion. The pieces are there, and must be assembled into a functionality.
- Efficient IMAP offline caching. Right now all mail is fetched everytime you launch the client, which obviously is not desirable. There's work being done on `QRESYNC`, `CONDSTORE`, and lazy fetch of messages when viewing a mailbox.
- More GPG support. Signatures can be verified but that's all that exists now. Encryption will be implemented along with WKD support.
- Custom action macros, for example pipe attachments to a script which is already possible with commands.
### Notes
- there is managesieve REPL binary in the repository. I haven't had the time to put managesieve functionality in the TUI yet.
- I haven't explored yet how to expose the API to users properly. I am thinking of using something like [rhai](https://github.com/jonathandturner/rhai) along with general MessagePack IPC.
- There is no API for UI widgets/graphics yet. I'm not sure how to design this right now.
- There's an old [implementation demo](https://git.meli.delivery/meli/meli/src/branch/master/src/plugins/python3/nntp-backend.py) for a mail backend in python using NNTP. It's probably not working anymore.
- There's an old [implementation demo](https://git.meli.delivery/meli/meli/src/branch/master/src/plugins/python3/ansii-plugin.py) for viewing images in ANSI in python using [https://github.com/stefanhaustein/TerminalImageViewer](https://github.com/stefanhaustein/TerminalImageViewer). It might not work anymore.
Follow me on [mastodon](https://chaos.social/@epilys) for updates. Join #meli on Freenode or with matrix's IRC bridge. I am interested in how you're using meli and fixing any problems you will probably encounter.

Some files were not shown because too many files have changed in this diff Show More