diff --git a/.gitignore b/.gitignore index b24dc86c..d8d6fd27 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ translations .env Rocket.toml !.gitkeep -static/media +static docker-compose.yml *.db *.sqlite @@ -16,8 +16,5 @@ docker-compose.yml tags.* !tags.rs search_index -main.css -*.wasm -*.js .buildconfig __pycache__ diff --git a/Cargo.lock b/Cargo.lock index 91f7f611..b80f17a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2084,8 +2084,10 @@ dependencies = [ "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "shrinkwraprs 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tantivy 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "webfinger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "whatlang 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/static/icons/trwnh/README.md b/assets/icons/trwnh/README.md similarity index 100% rename from static/icons/trwnh/README.md rename to assets/icons/trwnh/README.md diff --git a/static/icons/trwnh/avatar.png b/assets/icons/trwnh/avatar.png similarity index 100% rename from static/icons/trwnh/avatar.png rename to assets/icons/trwnh/avatar.png diff --git a/static/icons/trwnh/avatar.svg b/assets/icons/trwnh/avatar.svg similarity index 100% rename from static/icons/trwnh/avatar.svg rename to assets/icons/trwnh/avatar.svg diff --git a/static/icons/trwnh/avatar2.png b/assets/icons/trwnh/avatar2.png similarity index 100% rename from static/icons/trwnh/avatar2.png rename to assets/icons/trwnh/avatar2.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack.svg b/assets/icons/trwnh/feather-black/plumeFeatherBlack.svg similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack.svg rename to assets/icons/trwnh/feather-black/plumeFeatherBlack.svg diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack128.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack128.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack128.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack128.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack144.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack144.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack144.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack144.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack16.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack16.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack16.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack16.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack160.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack160.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack160.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack160.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack192.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack192.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack192.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack192.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack24.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack24.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack24.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack24.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack256.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack256.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack256.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack256.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack32.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack32.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack32.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack32.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack36.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack36.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack36.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack36.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack44.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack44.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack44.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack44.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack48.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack48.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack48.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack48.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack512.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack512.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack512.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack512.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack64.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack64.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack64.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack64.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack72.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack72.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack72.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack72.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack80.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack80.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack80.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack80.png diff --git a/static/icons/trwnh/feather-black/plumeFeatherBlack96.png b/assets/icons/trwnh/feather-black/plumeFeatherBlack96.png similarity index 100% rename from static/icons/trwnh/feather-black/plumeFeatherBlack96.png rename to assets/icons/trwnh/feather-black/plumeFeatherBlack96.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled.svg b/assets/icons/trwnh/feather-filled/plumeFeatherFilled.svg similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled.svg rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled.svg diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled128.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled128.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled128.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled128.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled144.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled144.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled144.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled144.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled16.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled16.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled16.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled16.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled160.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled160.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled160.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled160.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled192.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled192.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled192.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled192.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled24.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled24.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled24.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled24.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled256.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled256.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled256.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled256.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled32.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled32.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled32.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled32.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled36.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled36.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled36.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled36.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled44.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled44.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled44.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled44.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled48.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled48.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled48.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled48.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled512.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled512.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled512.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled512.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled64.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled64.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled64.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled64.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled72.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled72.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled72.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled72.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled80.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled80.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled80.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled80.png diff --git a/static/icons/trwnh/feather-filled/plumeFeatherFilled96.png b/assets/icons/trwnh/feather-filled/plumeFeatherFilled96.png similarity index 100% rename from static/icons/trwnh/feather-filled/plumeFeatherFilled96.png rename to assets/icons/trwnh/feather-filled/plumeFeatherFilled96.png diff --git a/static/icons/trwnh/feather/plumeFeather.svg b/assets/icons/trwnh/feather/plumeFeather.svg similarity index 100% rename from static/icons/trwnh/feather/plumeFeather.svg rename to assets/icons/trwnh/feather/plumeFeather.svg diff --git a/static/icons/trwnh/feather/plumeFeather128.png b/assets/icons/trwnh/feather/plumeFeather128.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather128.png rename to assets/icons/trwnh/feather/plumeFeather128.png diff --git a/static/icons/trwnh/feather/plumeFeather144.png b/assets/icons/trwnh/feather/plumeFeather144.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather144.png rename to assets/icons/trwnh/feather/plumeFeather144.png diff --git a/static/icons/trwnh/feather/plumeFeather16.png b/assets/icons/trwnh/feather/plumeFeather16.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather16.png rename to assets/icons/trwnh/feather/plumeFeather16.png diff --git a/static/icons/trwnh/feather/plumeFeather160.png b/assets/icons/trwnh/feather/plumeFeather160.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather160.png rename to assets/icons/trwnh/feather/plumeFeather160.png diff --git a/static/icons/trwnh/feather/plumeFeather192.png b/assets/icons/trwnh/feather/plumeFeather192.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather192.png rename to assets/icons/trwnh/feather/plumeFeather192.png diff --git a/static/icons/trwnh/feather/plumeFeather24.png b/assets/icons/trwnh/feather/plumeFeather24.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather24.png rename to assets/icons/trwnh/feather/plumeFeather24.png diff --git a/static/icons/trwnh/feather/plumeFeather256.png b/assets/icons/trwnh/feather/plumeFeather256.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather256.png rename to assets/icons/trwnh/feather/plumeFeather256.png diff --git a/static/icons/trwnh/feather/plumeFeather32.png b/assets/icons/trwnh/feather/plumeFeather32.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather32.png rename to assets/icons/trwnh/feather/plumeFeather32.png diff --git a/static/icons/trwnh/feather/plumeFeather36.png b/assets/icons/trwnh/feather/plumeFeather36.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather36.png rename to assets/icons/trwnh/feather/plumeFeather36.png diff --git a/static/icons/trwnh/feather/plumeFeather44.png b/assets/icons/trwnh/feather/plumeFeather44.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather44.png rename to assets/icons/trwnh/feather/plumeFeather44.png diff --git a/static/icons/trwnh/feather/plumeFeather48.png b/assets/icons/trwnh/feather/plumeFeather48.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather48.png rename to assets/icons/trwnh/feather/plumeFeather48.png diff --git a/static/icons/trwnh/feather/plumeFeather512.png b/assets/icons/trwnh/feather/plumeFeather512.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather512.png rename to assets/icons/trwnh/feather/plumeFeather512.png diff --git a/static/icons/trwnh/feather/plumeFeather64.png b/assets/icons/trwnh/feather/plumeFeather64.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather64.png rename to assets/icons/trwnh/feather/plumeFeather64.png diff --git a/static/icons/trwnh/feather/plumeFeather72.png b/assets/icons/trwnh/feather/plumeFeather72.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather72.png rename to assets/icons/trwnh/feather/plumeFeather72.png diff --git a/static/icons/trwnh/feather/plumeFeather80.png b/assets/icons/trwnh/feather/plumeFeather80.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather80.png rename to assets/icons/trwnh/feather/plumeFeather80.png diff --git a/static/icons/trwnh/feather/plumeFeather96.png b/assets/icons/trwnh/feather/plumeFeather96.png similarity index 100% rename from static/icons/trwnh/feather/plumeFeather96.png rename to assets/icons/trwnh/feather/plumeFeather96.png diff --git a/static/icons/trwnh/ideas.svg b/assets/icons/trwnh/ideas.svg similarity index 100% rename from static/icons/trwnh/ideas.svg rename to assets/icons/trwnh/ideas.svg diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack.svg b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack.svg similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack.svg rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack.svg diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack128.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack128.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack128.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack128.png diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack144.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack144.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack144.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack144.png diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack16.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack16.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack16.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack16.png diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack160.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack160.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack160.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack160.png diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack192.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack192.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack192.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack192.png diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack24.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack24.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack24.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack24.png diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack256.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack256.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack256.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack256.png diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack32.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack32.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack32.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack32.png diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack36.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack36.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack36.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack36.png diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack44.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack44.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack44.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack44.png diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack512.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack512.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack512.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack512.png diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack64.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack64.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack64.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack64.png diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack72.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack72.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack72.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack72.png diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack80.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack80.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack80.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack80.png diff --git a/static/icons/trwnh/paragraphs-black/plumeParagraphsBlack96.png b/assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack96.png similarity index 100% rename from static/icons/trwnh/paragraphs-black/plumeParagraphsBlack96.png rename to assets/icons/trwnh/paragraphs-black/plumeParagraphsBlack96.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs.svg b/assets/icons/trwnh/paragraphs/plumeParagraphs.svg similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs.svg rename to assets/icons/trwnh/paragraphs/plumeParagraphs.svg diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs128.png b/assets/icons/trwnh/paragraphs/plumeParagraphs128.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs128.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs128.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs144.png b/assets/icons/trwnh/paragraphs/plumeParagraphs144.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs144.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs144.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs16.png b/assets/icons/trwnh/paragraphs/plumeParagraphs16.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs16.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs16.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs160.png b/assets/icons/trwnh/paragraphs/plumeParagraphs160.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs160.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs160.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs192.png b/assets/icons/trwnh/paragraphs/plumeParagraphs192.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs192.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs192.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs24.png b/assets/icons/trwnh/paragraphs/plumeParagraphs24.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs24.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs24.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs256.png b/assets/icons/trwnh/paragraphs/plumeParagraphs256.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs256.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs256.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs32.png b/assets/icons/trwnh/paragraphs/plumeParagraphs32.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs32.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs32.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs36.png b/assets/icons/trwnh/paragraphs/plumeParagraphs36.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs36.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs36.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs44.png b/assets/icons/trwnh/paragraphs/plumeParagraphs44.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs44.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs44.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs48.png b/assets/icons/trwnh/paragraphs/plumeParagraphs48.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs48.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs48.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs512.png b/assets/icons/trwnh/paragraphs/plumeParagraphs512.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs512.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs512.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs64.png b/assets/icons/trwnh/paragraphs/plumeParagraphs64.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs64.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs64.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs72.png b/assets/icons/trwnh/paragraphs/plumeParagraphs72.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs72.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs72.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs80.png b/assets/icons/trwnh/paragraphs/plumeParagraphs80.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs80.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs80.png diff --git a/static/icons/trwnh/paragraphs/plumeParagraphs96.png b/assets/icons/trwnh/paragraphs/plumeParagraphs96.png similarity index 100% rename from static/icons/trwnh/paragraphs/plumeParagraphs96.png rename to assets/icons/trwnh/paragraphs/plumeParagraphs96.png diff --git a/static/images/audio-file.svg b/assets/images/audio-file.svg similarity index 100% rename from static/images/audio-file.svg rename to assets/images/audio-file.svg diff --git a/static/default-avatar.png b/assets/images/default-avatar.png similarity index 100% rename from static/default-avatar.png rename to assets/images/default-avatar.png diff --git a/static/images/feather-sprite.svg b/assets/images/feather-sprite.svg similarity index 100% rename from static/images/feather-sprite.svg rename to assets/images/feather-sprite.svg diff --git a/static/images/unknown-file.svg b/assets/images/unknown-file.svg similarity index 100% rename from static/images/unknown-file.svg rename to assets/images/unknown-file.svg diff --git a/static/images/video-file.svg b/assets/images/video-file.svg similarity index 100% rename from static/images/video-file.svg rename to assets/images/video-file.svg diff --git a/assets/themes/blog-monospace/theme.scss b/assets/themes/blog-monospace/theme.scss new file mode 100644 index 00000000..e3642d30 --- /dev/null +++ b/assets/themes/blog-monospace/theme.scss @@ -0,0 +1,3 @@ +* { + font-family: monospace; +} diff --git a/static/css/_article.scss b/assets/themes/default/_article.scss similarity index 89% rename from static/css/_article.scss rename to assets/themes/default/_article.scss index a3843d4f..c1191cef 100644 --- a/static/css/_article.scss +++ b/assets/themes/default/_article.scss @@ -1,8 +1,8 @@ // Heading main header.article { overflow: hidden; - background: $white; - color: $black; + background: $background; + color: $text-color; display: grid; background-size: cover; background-position: center; @@ -52,14 +52,14 @@ main header.article { height: 100%; width: 100%; - background: linear-gradient(180deg, transparent 20vh, black 80vh); + background: linear-gradient(180deg, transparent 20vh, $black 80vh); } & > img { z-index: 1; min-width: 100%; min-height: 100%; - background: $purple; + background: $primary; } } @@ -141,7 +141,7 @@ main .article-meta { padding: 0px; margin: 0px 10px 10px 0px; transition: all 0.2s ease-in; - border: 1px solid $purple; + border: 1px solid $primary; a { display: inline-block; @@ -149,7 +149,7 @@ main .article-meta { } &:hover { - background: transparentize($purple, 0.9); + background: transparentize($primary, 0.9); } } } @@ -181,7 +181,7 @@ main .article-meta { margin: 0; padding: 0; background: none; - color: $black; + color: $text-color; border: none; font-size: 1.1em; cursor: pointer; @@ -201,7 +201,7 @@ main .article-meta { &.reshared, &.liked { svg.feather { - color: $white; + color: $background; font-weight: 900; } } @@ -234,26 +234,26 @@ main .article-meta { } .reshares { - p, .action:hover { color: $purple; } + p, .action:hover { color: $primary; } .action svg.feather { padding: 0.7em; box-sizing: border-box; - color: $purple; - border: solid $purple thin; + color: $primary; + border: solid $primary thin; font-weight: 600; } .action:hover svg.feather { - background: transparentize($purple, 0.85); + background: transparentize($primary, 0.85); } .action.reshared svg.feather { - background: $purple; + background: $primary; } .action.reshared:hover svg.feather { - background: transparentize($purple, 0.75) - color: $purple; + background: transparentize($primary, 0.75) + color: $primary; } } @@ -262,7 +262,7 @@ main .article-meta { margin: 0 $horizontal-margin; h2 { - color: $purple; + color: $primary; font-size: 1.5em; font-weight: 600; } @@ -281,17 +281,17 @@ main .article-meta { a.button, form.inline, form.inline input { padding: 0; background: none; - color: $black; + color: $text-color; margin-right: 2em; font-family: $route159; font-weight: normal; &::before { - color: $purple; + color: $primary; padding-right: 0.5em; } - &:hover { color: $purple; } + &:hover { color: $primary; } } .comment { @@ -325,7 +325,7 @@ main .article-meta { } .dt-published a { - color: transparentize($black, 0.6); + color: transparentize($text-color, 0.6); } .author { @@ -339,11 +339,11 @@ main .article-meta { } .display-name { - color: $black; + color: $text-color; } &:hover { - .display-name { color: $purple; } + .display-name { color: $primary; } small { opacity: 1; } } } @@ -384,7 +384,7 @@ main .article-meta { } .placeholder { - color: transparentize($black, 0.6); + color: transparentize($text-color, 0.6); } article { @@ -400,7 +400,7 @@ main .article-meta { left: 20vw; right: 20vw; background: $gray; - border: 1px solid $purple; + border: 1px solid $primary; z-index: 2; padding: 2em; overflow-y: auto; diff --git a/assets/themes/default/_dark_variables.scss b/assets/themes/default/_dark_variables.scss new file mode 100644 index 00000000..2d1b9fd4 --- /dev/null +++ b/assets/themes/default/_dark_variables.scss @@ -0,0 +1,19 @@ +@import '_variables'; + +// Color Scheme +$gray: #1a3854; +$black: #102e4a; +$white: #F8F8F8; +$purple: #7765E3; +$lightpurple: #c2bbee; +$red: #d16666; +$yellow: #ff934f; +$blue: #7f96ff; + +$background: $black; +$form-input-background: $gray; +$form-input-border: $white; +$text-color: $white; +$primary: $purple; +$primary-text-color: $white; // text color on primary background (buttons for instance) +$success-color: $blue; diff --git a/static/css/_forms.scss b/assets/themes/default/_forms.scss similarity index 89% rename from static/css/_forms.scss rename to assets/themes/default/_forms.scss index 7b451d4f..7e4f0167 100644 --- a/static/css/_forms.scss +++ b/assets/themes/default/_forms.scss @@ -13,14 +13,14 @@ input, textarea, select { -webkit-appearance: textarea; background: $form-input-background; - color: $black; - border: solid $black thin; + color: $text-color; + border: solid $form-input-border thin; font-size: 1.2em; font-weight: 400; &:focus { - border-color: $purple; + border-color: $primary; } } form input[type="submit"] { @@ -64,7 +64,7 @@ form.inline { padding: 0; border: none; background: transparent; - color: $purple; + color: $primary; font-weight: normal; } } @@ -78,15 +78,15 @@ form.inline { margin: 0.5em auto; padding: 0.75em 1em; - background: $purple; - color: $white; + background: $primary; + color: $primary-text-color; font-weight: bold; border: none; cursor: pointer; &:hover { - background: transparentize($purple, 0.1); + background: transparentize($primary, 0.1); } &.destructive { @@ -99,10 +99,10 @@ form.inline { &.secondary { background: $gray; - color: $black; + color: $text-color; &:hover { - background: transparentize($black, 0.9); + background: transparentize($text-color, 0.9); } } } diff --git a/static/css/_global.scss b/assets/themes/default/_global.scss similarity index 63% rename from static/css/_global.scss rename to assets/themes/default/_global.scss index 8bc5a426..6ac03246 100644 --- a/static/css/_global.scss +++ b/assets/themes/default/_global.scss @@ -1,31 +1,38 @@ +html { + box-sizing: border-box; +} +*, *:before, *:after { + box-sizing: inherit; +} + html, body { margin: 0; padding: 0; background: $background; - color: $black; + color: $text-color; font-family: $route159; ::selection { - background: transparentize($purple, 0.7); + background: transparentize($primary, 0.7); } ::-moz-selection { - background: transparentize($purple, 0.7); + background: transparentize($primary, 0.7); } } a, a:visited { - color: $purple; + color: $primary; text-decoration: none; } a::selection { - color: $white; + color: $background; } a::-moz-selection { - color: $white; + color: $background; } small { margin-left: 1em; - color: transparentize($black, 0.6); + color: transparentize($text-color, 0.6); font-size: 0.75em; word-wrap: break-word; word-break: break-all; @@ -152,9 +159,9 @@ p.error { margin-right: 1em; padding: 0.35em 1em; - background: $white; - color: $purple; - border: 1px solid $purple; + background: $background; + color: $primary; + border: 1px solid $primary; font-size: 1rem; } @@ -203,9 +210,9 @@ p.error { font-weight: normal; a { transition: color 0.1s ease-in; - color: $black; + color: $text-color; - &:hover { color: $purple; } + &:hover { color: $primary; } } } @@ -326,8 +333,8 @@ body > footer { display: flex; align-content: center; justify-content: space-around; - background: $purple; - color: $white; + background: $primary; + color: $primary-text-color; margin-top: 5em; * { @@ -336,13 +343,13 @@ body > footer { hr { transform: skew(-15deg); - background: $white; + background: $primary-text-color; border: none; width: .2em; } a, a:visited { - color: $white; + color: $primary-text-color; } div { @@ -445,12 +452,170 @@ figure { a { display: inline-block; - color: $black; + color: $text-color; padding: 1em; &.selected { - color: $purple; - border-bottom: 1px solid $purple; + color: $primary; + border-bottom: 1px solid $primary; } } } + + +/// Small screens +@media screen and (max-width: 600px) { + @keyframes menuOpening { + from { + transform: scaleX(0); + transform-origin: left; + opacity: 0; + } + to { + transform: scaleX(1); + transform-origin: left; + opacity: 1; + } + } + + body > header { + flex-direction: column; + + nav#menu { + display: inline-flex; + z-index: 21; + } + + #content { + display: none; + appearance: none; + text-align: center; + z-index: 20; + } + } + + body > header:focus-within #content, #content.show { + position: fixed; + display: flex; + flex-direction: column; + justify-content: flex-start; + + top: 0; + left: 0; + width: 100%; + height: 100%; + box-sizing: border-box; + + animation: 0.2s menuOpening; + + &::before { + content: ""; + position: absolute; + transform: skewX(-10deg); + top: 0; + left: -20%; + width: 100%; + height: 100%; + + z-index: -10; + + background: $primary; + } + + > nav { + flex-direction: column; + align-items: flex-start; + + a { + display: flex; + flex-direction: row; + align-items: center; + margin: 0; + padding: 1rem 1.5rem; + color: $background; + font-size: 1.4em; + font-weight: 300; + + &.title { font-size: 1.8em; } + + > *:first-child { width: 3rem; } + > img:first-child { height: 3rem; } + > *:last-child { margin-left: 1rem; } + > nav hr { + display: block; + margin: 0; + width: 100%; + border: solid $background 0.1rem; + } + .mobile-label { display: initial; } + } + } + } + + main .article-meta { + > *, .comments { + margin: 0 5%; + } + > p { + margin: 2em 5%; + font-size: 0.9em; + } + .comments > * { margin: auto 5%; } + .comments .comment { padding: 2em 0px; } + } + main .article-info, main article, main h1.article, main h2.article { + max-width: 90vw; + } + + .card { + min-width: 80%; + min-height: 80%; + } + + .tabs { + margin: auto 0px 2em; + } + + .stats { flex-direction: column; } + body > footer { + flex-direction: column; + align-items: center; + } + body > footer * { + margin: 1em auto; + text-align: center; + } + + .flex.wrap { flex-direction: column; } + + .cards, .list { + margin: 1rem 0 5rem; + } + + .split { + flex-direction: column; + margin: 0; + + & > * { + max-width: 100%; + } + } + + .bottom-bar { + flex-direction: column; + align-items: center; + & > div { + margin: 0; + } + } + + main .article-meta .comments .comment { + header { + flex-direction: column; + } + + .content { + margin-top: 0.5em; + } + } +} diff --git a/static/css/_header.scss b/assets/themes/default/_header.scss similarity index 94% rename from static/css/_header.scss rename to assets/themes/default/_header.scss index 96497526..369be572 100644 --- a/static/css/_header.scss +++ b/assets/themes/default/_header.scss @@ -14,7 +14,7 @@ body > header { transform: skewX(-15deg); left: -1em; padding: 1em 1em 1em 2em; - background: $purple; + background: $primary; align-self: flex-start; a { @@ -40,7 +40,7 @@ body > header { hr { height: 100%; width: 0.2em; - background: $purple; + background: $primary; border: none; transform: skewX(-15deg); } @@ -96,8 +96,8 @@ body > header { } p.success { - color: darken($green, 20%); - background: lighten($green, 40%); + color: darken($success-color, 20%); + background: lighten($success-color, 40%); } } diff --git a/static/css/_variables.scss b/assets/themes/default/_variables.scss similarity index 69% rename from static/css/_variables.scss rename to assets/themes/default/_variables.scss index 22098f2c..d6bbf1d0 100644 --- a/static/css/_variables.scss +++ b/assets/themes/default/_variables.scss @@ -10,6 +10,11 @@ $green: #23f0c7; $background: $white; $form-input-background: white; +$form-input-border: $black; +$text-color: $black; +$primary: $purple; +$primary-text-color: $white; // text color on primary background (buttons for instance) +$success-color: $green; // Dimensions diff --git a/assets/themes/default/dark.scss b/assets/themes/default/dark.scss new file mode 100644 index 00000000..6ffcd72f --- /dev/null +++ b/assets/themes/default/dark.scss @@ -0,0 +1,12 @@ +/* color palette: https://coolors.co/23f0c7-ef767a-7765e3-6457a6-ffe347 */ + +@import url('./feather.css'); +@import url('./fonts/Route159/Route159.css'); +@import url('./fonts/Lora/Lora.css'); +@import url('./fonts/Playfair_Display/PlayfairDisplay.css'); + +@import 'dark_variables'; +@import 'global'; +@import 'header'; +@import 'article'; +@import 'forms'; diff --git a/static/css/feather.css b/assets/themes/default/feather.css similarity index 96% rename from static/css/feather.css rename to assets/themes/default/feather.css index 7f2d1292..e90dd3ba 100644 --- a/static/css/feather.css +++ b/assets/themes/default/feather.css @@ -1,10 +1,10 @@ @font-face { font-family: "Feather"; - src: url('../fonts/Feather/Feather.eot'); /* IE9 */ - src: url('../fonts/Feather/Feather.eot') format('embedded-opentype'), /* IE6-IE8 */ - url('../fonts/Feather/Feather.woff') format('woff'), /* Chrome, Firefox */ - url('../fonts/Feather/Feather.ttf') format('truetype'), /* Chrome, Firefox, Opera, Safari, Android, iOS 4.2+ */ - url('../fonts/Feather/Feather.svg') format('svg'); /* iOS 4.1- */ + src: url('./fonts/Feather/Feather.eot'); /* IE9 */ + src: url('./fonts/Feather/Feather.eot') format('embedded-opentype'), /* IE6-IE8 */ + url('./fonts/Feather/Feather.woff') format('woff'), /* Chrome, Firefox */ + url('./fonts/Feather/Feather.ttf') format('truetype'), /* Chrome, Firefox, Opera, Safari, Android, iOS 4.2+ */ + url('./fonts/Feather/Feather.svg') format('svg'); /* iOS 4.1- */ } .feather { diff --git a/static/fonts/Feather/Feather.eot b/assets/themes/default/fonts/Feather/Feather.eot similarity index 100% rename from static/fonts/Feather/Feather.eot rename to assets/themes/default/fonts/Feather/Feather.eot diff --git a/static/fonts/Feather/Feather.svg b/assets/themes/default/fonts/Feather/Feather.svg similarity index 100% rename from static/fonts/Feather/Feather.svg rename to assets/themes/default/fonts/Feather/Feather.svg diff --git a/static/fonts/Feather/Feather.ttf b/assets/themes/default/fonts/Feather/Feather.ttf similarity index 100% rename from static/fonts/Feather/Feather.ttf rename to assets/themes/default/fonts/Feather/Feather.ttf diff --git a/static/fonts/Feather/Feather.woff b/assets/themes/default/fonts/Feather/Feather.woff similarity index 100% rename from static/fonts/Feather/Feather.woff rename to assets/themes/default/fonts/Feather/Feather.woff diff --git a/static/fonts/Lora/Lora-Bold.eot b/assets/themes/default/fonts/Lora/Lora-Bold.eot similarity index 100% rename from static/fonts/Lora/Lora-Bold.eot rename to assets/themes/default/fonts/Lora/Lora-Bold.eot diff --git a/static/fonts/Lora/Lora-Bold.ttf b/assets/themes/default/fonts/Lora/Lora-Bold.ttf similarity index 100% rename from static/fonts/Lora/Lora-Bold.ttf rename to assets/themes/default/fonts/Lora/Lora-Bold.ttf diff --git a/static/fonts/Lora/Lora-Bold.woff b/assets/themes/default/fonts/Lora/Lora-Bold.woff similarity index 100% rename from static/fonts/Lora/Lora-Bold.woff rename to assets/themes/default/fonts/Lora/Lora-Bold.woff diff --git a/static/fonts/Lora/Lora-Bold.woff2 b/assets/themes/default/fonts/Lora/Lora-Bold.woff2 similarity index 100% rename from static/fonts/Lora/Lora-Bold.woff2 rename to assets/themes/default/fonts/Lora/Lora-Bold.woff2 diff --git a/static/fonts/Lora/Lora-BoldItalic.eot b/assets/themes/default/fonts/Lora/Lora-BoldItalic.eot similarity index 100% rename from static/fonts/Lora/Lora-BoldItalic.eot rename to assets/themes/default/fonts/Lora/Lora-BoldItalic.eot diff --git a/static/fonts/Lora/Lora-BoldItalic.ttf b/assets/themes/default/fonts/Lora/Lora-BoldItalic.ttf similarity index 100% rename from static/fonts/Lora/Lora-BoldItalic.ttf rename to assets/themes/default/fonts/Lora/Lora-BoldItalic.ttf diff --git a/static/fonts/Lora/Lora-BoldItalic.woff b/assets/themes/default/fonts/Lora/Lora-BoldItalic.woff similarity index 100% rename from static/fonts/Lora/Lora-BoldItalic.woff rename to assets/themes/default/fonts/Lora/Lora-BoldItalic.woff diff --git a/static/fonts/Lora/Lora-BoldItalic.woff2 b/assets/themes/default/fonts/Lora/Lora-BoldItalic.woff2 similarity index 100% rename from static/fonts/Lora/Lora-BoldItalic.woff2 rename to assets/themes/default/fonts/Lora/Lora-BoldItalic.woff2 diff --git a/static/fonts/Lora/Lora-Italic.eot b/assets/themes/default/fonts/Lora/Lora-Italic.eot similarity index 100% rename from static/fonts/Lora/Lora-Italic.eot rename to assets/themes/default/fonts/Lora/Lora-Italic.eot diff --git a/static/fonts/Lora/Lora-Italic.ttf b/assets/themes/default/fonts/Lora/Lora-Italic.ttf similarity index 100% rename from static/fonts/Lora/Lora-Italic.ttf rename to assets/themes/default/fonts/Lora/Lora-Italic.ttf diff --git a/static/fonts/Lora/Lora-Italic.woff b/assets/themes/default/fonts/Lora/Lora-Italic.woff similarity index 100% rename from static/fonts/Lora/Lora-Italic.woff rename to assets/themes/default/fonts/Lora/Lora-Italic.woff diff --git a/static/fonts/Lora/Lora-Italic.woff2 b/assets/themes/default/fonts/Lora/Lora-Italic.woff2 similarity index 100% rename from static/fonts/Lora/Lora-Italic.woff2 rename to assets/themes/default/fonts/Lora/Lora-Italic.woff2 diff --git a/static/fonts/Lora/Lora-Regular.eot b/assets/themes/default/fonts/Lora/Lora-Regular.eot similarity index 100% rename from static/fonts/Lora/Lora-Regular.eot rename to assets/themes/default/fonts/Lora/Lora-Regular.eot diff --git a/static/fonts/Lora/Lora-Regular.ttf b/assets/themes/default/fonts/Lora/Lora-Regular.ttf similarity index 100% rename from static/fonts/Lora/Lora-Regular.ttf rename to assets/themes/default/fonts/Lora/Lora-Regular.ttf diff --git a/static/fonts/Lora/Lora-Regular.woff b/assets/themes/default/fonts/Lora/Lora-Regular.woff similarity index 100% rename from static/fonts/Lora/Lora-Regular.woff rename to assets/themes/default/fonts/Lora/Lora-Regular.woff diff --git a/static/fonts/Lora/Lora-Regular.woff2 b/assets/themes/default/fonts/Lora/Lora-Regular.woff2 similarity index 100% rename from static/fonts/Lora/Lora-Regular.woff2 rename to assets/themes/default/fonts/Lora/Lora-Regular.woff2 diff --git a/static/fonts/Lora/Lora.css b/assets/themes/default/fonts/Lora/Lora.css similarity index 100% rename from static/fonts/Lora/Lora.css rename to assets/themes/default/fonts/Lora/Lora.css diff --git a/static/fonts/Lora/OFL.txt b/assets/themes/default/fonts/Lora/OFL.txt similarity index 100% rename from static/fonts/Lora/OFL.txt rename to assets/themes/default/fonts/Lora/OFL.txt diff --git a/static/fonts/Playfair_Display/OFL.txt b/assets/themes/default/fonts/Playfair_Display/OFL.txt similarity index 100% rename from static/fonts/Playfair_Display/OFL.txt rename to assets/themes/default/fonts/Playfair_Display/OFL.txt diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Black.eot b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Black.eot similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Black.eot rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Black.eot diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Black.ttf b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Black.ttf similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Black.ttf rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Black.ttf diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Black.woff b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Black.woff similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Black.woff rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Black.woff diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Black.woff2 b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Black.woff2 similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Black.woff2 rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Black.woff2 diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.eot b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.eot similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.eot rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.eot diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.ttf b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.ttf similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.ttf rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.ttf diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.woff b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.woff similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.woff rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.woff diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.woff2 b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.woff2 similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.woff2 rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BlackItalic.woff2 diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Bold.eot b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Bold.eot similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Bold.eot rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Bold.eot diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Bold.ttf b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Bold.ttf similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Bold.ttf rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Bold.ttf diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Bold.woff b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Bold.woff similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Bold.woff rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Bold.woff diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Bold.woff2 b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Bold.woff2 similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Bold.woff2 rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Bold.woff2 diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.eot b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.eot similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.eot rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.eot diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.ttf b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.ttf similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.ttf rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.ttf diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.woff b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.woff similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.woff rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.woff diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.woff2 b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.woff2 similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.woff2 rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-BoldItalic.woff2 diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Italic.eot b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Italic.eot similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Italic.eot rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Italic.eot diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Italic.ttf b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Italic.ttf similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Italic.ttf rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Italic.ttf diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Italic.woff b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Italic.woff similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Italic.woff rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Italic.woff diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Italic.woff2 b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Italic.woff2 similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Italic.woff2 rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Italic.woff2 diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Regular.eot b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Regular.eot similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Regular.eot rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Regular.eot diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Regular.ttf b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Regular.ttf similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Regular.ttf rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Regular.ttf diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Regular.woff b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Regular.woff similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Regular.woff rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Regular.woff diff --git a/static/fonts/Playfair_Display/PlayfairDisplay-Regular.woff2 b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Regular.woff2 similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay-Regular.woff2 rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay-Regular.woff2 diff --git a/static/fonts/Playfair_Display/PlayfairDisplay.css b/assets/themes/default/fonts/Playfair_Display/PlayfairDisplay.css similarity index 100% rename from static/fonts/Playfair_Display/PlayfairDisplay.css rename to assets/themes/default/fonts/Playfair_Display/PlayfairDisplay.css diff --git a/static/fonts/Route159/Route159-Bold.eot b/assets/themes/default/fonts/Route159/Route159-Bold.eot similarity index 100% rename from static/fonts/Route159/Route159-Bold.eot rename to assets/themes/default/fonts/Route159/Route159-Bold.eot diff --git a/static/fonts/Route159/Route159-Bold.woff b/assets/themes/default/fonts/Route159/Route159-Bold.woff similarity index 100% rename from static/fonts/Route159/Route159-Bold.woff rename to assets/themes/default/fonts/Route159/Route159-Bold.woff diff --git a/static/fonts/Route159/Route159-BoldItalic.eot b/assets/themes/default/fonts/Route159/Route159-BoldItalic.eot similarity index 100% rename from static/fonts/Route159/Route159-BoldItalic.eot rename to assets/themes/default/fonts/Route159/Route159-BoldItalic.eot diff --git a/static/fonts/Route159/Route159-BoldItalic.woff b/assets/themes/default/fonts/Route159/Route159-BoldItalic.woff similarity index 100% rename from static/fonts/Route159/Route159-BoldItalic.woff rename to assets/themes/default/fonts/Route159/Route159-BoldItalic.woff diff --git a/static/fonts/Route159/Route159-Heavy.eot b/assets/themes/default/fonts/Route159/Route159-Heavy.eot similarity index 100% rename from static/fonts/Route159/Route159-Heavy.eot rename to assets/themes/default/fonts/Route159/Route159-Heavy.eot diff --git a/static/fonts/Route159/Route159-Heavy.woff b/assets/themes/default/fonts/Route159/Route159-Heavy.woff similarity index 100% rename from static/fonts/Route159/Route159-Heavy.woff rename to assets/themes/default/fonts/Route159/Route159-Heavy.woff diff --git a/static/fonts/Route159/Route159-HeavyItalic.eot b/assets/themes/default/fonts/Route159/Route159-HeavyItalic.eot similarity index 100% rename from static/fonts/Route159/Route159-HeavyItalic.eot rename to assets/themes/default/fonts/Route159/Route159-HeavyItalic.eot diff --git a/static/fonts/Route159/Route159-HeavyItalic.woff b/assets/themes/default/fonts/Route159/Route159-HeavyItalic.woff similarity index 100% rename from static/fonts/Route159/Route159-HeavyItalic.woff rename to assets/themes/default/fonts/Route159/Route159-HeavyItalic.woff diff --git a/static/fonts/Route159/Route159-Italic.eot b/assets/themes/default/fonts/Route159/Route159-Italic.eot similarity index 100% rename from static/fonts/Route159/Route159-Italic.eot rename to assets/themes/default/fonts/Route159/Route159-Italic.eot diff --git a/static/fonts/Route159/Route159-Italic.woff b/assets/themes/default/fonts/Route159/Route159-Italic.woff similarity index 100% rename from static/fonts/Route159/Route159-Italic.woff rename to assets/themes/default/fonts/Route159/Route159-Italic.woff diff --git a/static/fonts/Route159/Route159-Light.eot b/assets/themes/default/fonts/Route159/Route159-Light.eot similarity index 100% rename from static/fonts/Route159/Route159-Light.eot rename to assets/themes/default/fonts/Route159/Route159-Light.eot diff --git a/static/fonts/Route159/Route159-Light.woff b/assets/themes/default/fonts/Route159/Route159-Light.woff similarity index 100% rename from static/fonts/Route159/Route159-Light.woff rename to assets/themes/default/fonts/Route159/Route159-Light.woff diff --git a/static/fonts/Route159/Route159-LightItalic.eot b/assets/themes/default/fonts/Route159/Route159-LightItalic.eot similarity index 100% rename from static/fonts/Route159/Route159-LightItalic.eot rename to assets/themes/default/fonts/Route159/Route159-LightItalic.eot diff --git a/static/fonts/Route159/Route159-LightItalic.woff b/assets/themes/default/fonts/Route159/Route159-LightItalic.woff similarity index 100% rename from static/fonts/Route159/Route159-LightItalic.woff rename to assets/themes/default/fonts/Route159/Route159-LightItalic.woff diff --git a/static/fonts/Route159/Route159-Regular.eot b/assets/themes/default/fonts/Route159/Route159-Regular.eot similarity index 100% rename from static/fonts/Route159/Route159-Regular.eot rename to assets/themes/default/fonts/Route159/Route159-Regular.eot diff --git a/static/fonts/Route159/Route159-Regular.woff b/assets/themes/default/fonts/Route159/Route159-Regular.woff similarity index 100% rename from static/fonts/Route159/Route159-Regular.woff rename to assets/themes/default/fonts/Route159/Route159-Regular.woff diff --git a/static/fonts/Route159/Route159-SemiBold.eot b/assets/themes/default/fonts/Route159/Route159-SemiBold.eot similarity index 100% rename from static/fonts/Route159/Route159-SemiBold.eot rename to assets/themes/default/fonts/Route159/Route159-SemiBold.eot diff --git a/static/fonts/Route159/Route159-SemiBold.woff b/assets/themes/default/fonts/Route159/Route159-SemiBold.woff similarity index 100% rename from static/fonts/Route159/Route159-SemiBold.woff rename to assets/themes/default/fonts/Route159/Route159-SemiBold.woff diff --git a/static/fonts/Route159/Route159-SemiBoldItalic.eot b/assets/themes/default/fonts/Route159/Route159-SemiBoldItalic.eot similarity index 100% rename from static/fonts/Route159/Route159-SemiBoldItalic.eot rename to assets/themes/default/fonts/Route159/Route159-SemiBoldItalic.eot diff --git a/static/fonts/Route159/Route159-SemiBoldItalic.woff b/assets/themes/default/fonts/Route159/Route159-SemiBoldItalic.woff similarity index 100% rename from static/fonts/Route159/Route159-SemiBoldItalic.woff rename to assets/themes/default/fonts/Route159/Route159-SemiBoldItalic.woff diff --git a/static/fonts/Route159/Route159-UltraLight.eot b/assets/themes/default/fonts/Route159/Route159-UltraLight.eot similarity index 100% rename from static/fonts/Route159/Route159-UltraLight.eot rename to assets/themes/default/fonts/Route159/Route159-UltraLight.eot diff --git a/static/fonts/Route159/Route159-UltraLight.woff b/assets/themes/default/fonts/Route159/Route159-UltraLight.woff similarity index 100% rename from static/fonts/Route159/Route159-UltraLight.woff rename to assets/themes/default/fonts/Route159/Route159-UltraLight.woff diff --git a/static/fonts/Route159/Route159-UltraLightItalic.eot b/assets/themes/default/fonts/Route159/Route159-UltraLightItalic.eot similarity index 100% rename from static/fonts/Route159/Route159-UltraLightItalic.eot rename to assets/themes/default/fonts/Route159/Route159-UltraLightItalic.eot diff --git a/static/fonts/Route159/Route159-UltraLightItalic.woff b/assets/themes/default/fonts/Route159/Route159-UltraLightItalic.woff similarity index 100% rename from static/fonts/Route159/Route159-UltraLightItalic.woff rename to assets/themes/default/fonts/Route159/Route159-UltraLightItalic.woff diff --git a/static/fonts/Route159/Route159.css b/assets/themes/default/fonts/Route159/Route159.css similarity index 100% rename from static/fonts/Route159/Route159.css rename to assets/themes/default/fonts/Route159/Route159.css diff --git a/assets/themes/default/light.scss b/assets/themes/default/light.scss new file mode 100644 index 00000000..be49dfc8 --- /dev/null +++ b/assets/themes/default/light.scss @@ -0,0 +1,12 @@ +/* color palette: https://coolors.co/23f0c7-ef767a-7765e3-6457a6-ffe347 */ + +@import url('./feather.css'); +@import url('./fonts/Route159/Route159.css'); +@import url('./fonts/Lora/Lora.css'); +@import url('./fonts/Playfair_Display/PlayfairDisplay.css'); + +@import 'variables'; +@import 'global'; +@import 'header'; +@import 'article'; +@import 'forms'; diff --git a/build.rs b/build.rs index 812a4202..c02deb59 100644 --- a/build.rs +++ b/build.rs @@ -2,7 +2,7 @@ extern crate rsass; extern crate ructe; use ructe::*; use std::process::{Command, Stdio}; -use std::{env, fs::*, io::Write, path::PathBuf}; +use std::{env, ffi::OsStr, fs::*, io::Write, path::*}; fn compute_static_hash() -> String { //"find static/ -type f ! -path 'static/media/*' | sort | xargs stat -c'%n %Y' | openssl dgst -r" @@ -41,21 +41,12 @@ fn main() { let in_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("templates"); compile_templates(&in_dir, &out_dir).expect("compile templates"); - println!("cargo:rerun-if-changed=static/css/_article.scss"); - println!("cargo:rerun-if-changed=static/css/_forms.scss"); - println!("cargo:rerun-if-changed=static/css/_global.scss"); - println!("cargo:rerun-if-changed=static/css/_header.scss"); - println!("cargo:rerun-if-changed=static/css/_variables.scss"); - println!("cargo:rerun-if-changed=static/css/main.scss"); - let mut out = File::create("static/css/main.css").expect("Couldn't create main.css"); - out.write_all( - &rsass::compile_scss_file( - "static/css/main.scss".as_ref(), - rsass::OutputStyle::Compressed, - ) - .expect("Error during SCSS compilation"), - ) - .expect("Couldn't write CSS output"); + compile_themes().expect("Theme compilation error"); + recursive_copy(&Path::new("assets").join("icons"), &Path::new("static")) + .expect("Couldn't copy icons"); + recursive_copy(&Path::new("assets").join("images"), &Path::new("static")) + .expect("Couldn't copy images"); + create_dir_all(&Path::new("static").join("media")).expect("Couldn't init media directory"); let cache_id = &compute_static_hash()[..8]; println!("cargo:rerun-if-changed=target/deploy/plume-front.wasm"); @@ -74,3 +65,91 @@ fn main() { println!("cargo:rustc-env=CACHE_ID={}", cache_id) } + +fn compile_themes() -> std::io::Result<()> { + let input_dir = Path::new("assets").join("themes"); + let output_dir = Path::new("static").join("css"); + + let themes = find_themes(input_dir)?; + + for theme in themes { + compile_theme(&theme, &output_dir)?; + } + + Ok(()) +} + +fn find_themes(path: PathBuf) -> std::io::Result> { + let ext = path.extension().and_then(OsStr::to_str); + if metadata(&path)?.is_dir() { + Ok(read_dir(&path)?.fold(vec![], |mut themes, ch| { + if let Ok(ch) = ch { + if let Ok(mut new) = find_themes(ch.path()) { + themes.append(&mut new); + } + } + themes + })) + } else if (ext == Some("scss") || ext == Some("sass")) + && !path.file_name().unwrap().to_str().unwrap().starts_with('_') + { + Ok(vec![path.clone()]) + } else { + Ok(vec![]) + } +} + +fn compile_theme(path: &Path, out_dir: &Path) -> std::io::Result<()> { + let name = path + .components() + .skip_while(|c| *c != Component::Normal(OsStr::new("themes"))) + .skip(1) + .filter_map(|c| { + c.as_os_str() + .to_str() + .unwrap_or_default() + .splitn(2, '.') + .next() + }) + .collect::>() + .join("-"); + + let dir = path.parent().unwrap(); + + let out = out_dir.join(name); + create_dir_all(&out)?; + + // copy files of the theme that are not scss + for ch in read_dir(&dir)? { + recursive_copy(&ch?.path(), &out)?; + } + + // compile the .scss/.sass file + let mut out = File::create(out.join("theme.css"))?; + out.write_all( + &rsass::compile_scss_file(path, rsass::OutputStyle::Compressed) + .expect("SCSS compilation error"), + )?; + + Ok(()) +} + +fn recursive_copy(path: &Path, out_dir: &Path) -> std::io::Result<()> { + if metadata(path)?.is_dir() { + let out = out_dir.join(path.file_name().unwrap()); + create_dir_all(out.clone())?; + + for ch in read_dir(path)? { + recursive_copy(&ch?.path(), &out)?; + } + } else { + println!("cargo:rerun-if-changed={}", path.display()); + + let ext = path.extension().and_then(OsStr::to_str); + if ext != Some("scss") && ext != Some("sass") { + copy(path, out_dir.join(path.file_name().unwrap()))?; + } + } + + Ok(()) +} diff --git a/migrations/postgres/2019-06-19-141114_themes/down.sql b/migrations/postgres/2019-06-19-141114_themes/down.sql new file mode 100644 index 00000000..54e85dff --- /dev/null +++ b/migrations/postgres/2019-06-19-141114_themes/down.sql @@ -0,0 +1,4 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE blogs DROP COLUMN theme; +ALTER TABLE users DROP COLUMN preferred_theme; +ALTER TABLE users DROP COLUMN hide_custom_css; diff --git a/migrations/postgres/2019-06-19-141114_themes/up.sql b/migrations/postgres/2019-06-19-141114_themes/up.sql new file mode 100644 index 00000000..5a92b2a0 --- /dev/null +++ b/migrations/postgres/2019-06-19-141114_themes/up.sql @@ -0,0 +1,4 @@ +-- Your SQL goes here +ALTER TABLE blogs ADD COLUMN theme VARCHAR; +ALTER TABLE users ADD COLUMN preferred_theme VARCHAR; +ALTER TABLE users ADD COLUMN hide_custom_css BOOLEAN NOT NULL DEFAULT 'f'; diff --git a/migrations/sqlite/2019-06-21-154916_themes/down.sql b/migrations/sqlite/2019-06-21-154916_themes/down.sql new file mode 100644 index 00000000..78599e7d --- /dev/null +++ b/migrations/sqlite/2019-06-21-154916_themes/down.sql @@ -0,0 +1,88 @@ +-- This file should undo anything in `up.sql` + +CREATE TABLE blogs_before_themes ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + actor_id VARCHAR NOT NULL, + title VARCHAR NOT NULL, + summary TEXT NOT NULL DEFAULT '', + outbox_url VARCHAR NOT NULL UNIQUE, + inbox_url VARCHAR NOT NULL UNIQUE, + instance_id INTEGER REFERENCES instances(id) ON DELETE CASCADE NOT NULL, + creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + ap_url text not null default '' UNIQUE, + private_key TEXT, + public_key TEXT NOT NULL DEFAULT '', + fqn TEXT NOT NULL DEFAULT '', + summary_html TEXT NOT NULL DEFAULT '', + icon_id INTEGER REFERENCES medias(id) ON DELETE SET NULL DEFAULT NULL, + banner_id INTEGER REFERENCES medias(id) ON DELETE SET NULL DEFAULT NULL, + CONSTRAINT blog_unique UNIQUE (actor_id, instance_id) +); +INSERT INTO blogs_before_themes SELECT + id, + actor_id, + title, + summary, + outbox_url, + inbox_url, + instance_id, + creation_date, + ap_url, + private_key, + public_key, + fqn, + summary_html, + icon_id, + banner_id +FROM blogs; +DROP TABLE blogs; +ALTER TABLE blogs_before_themes RENAME TO blogs; + +CREATE TABLE users_before_themes ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + username VARCHAR NOT NULL, + display_name VARCHAR NOT NULL DEFAULT '', + outbox_url VARCHAR NOT NULL UNIQUE, + inbox_url VARCHAR NOT NULL UNIQUE, + is_admin BOOLEAN NOT NULL DEFAULT 'f', + summary TEXT NOT NULL DEFAULT '', + email TEXT, + hashed_password TEXT, + instance_id INTEGER REFERENCES instances(id) ON DELETE CASCADE NOT NULL, + creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + ap_url TEXT NOT NULL default '' UNIQUE, + private_key TEXT, + public_key TEXT NOT NULL DEFAULT '', + shared_inbox_url VARCHAR, + followers_endpoint VARCHAR NOT NULL DEFAULT '' UNIQUE, + avatar_id INTEGER REFERENCES medias(id) ON DELETE CASCADE, + last_fetched_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + fqn TEXT NOT NULL DEFAULT '', + summary_html TEXT NOT NULL DEFAULT '', + FOREIGN KEY (avatar_id) REFERENCES medias(id) ON DELETE SET NULL, + CONSTRAINT blog_authors_unique UNIQUE (username, instance_id) +); +INSERT INTO users_before_themes SELECT + id, + username, + display_name, + outbox_url, + inbox_url, + is_admin, + summary, + email, + hashed_password, + instance_id, + creation_date, + ap_url, + private_key, + public_key, + shared_inbox_url, + followers_endpoint, + avatar_id, + last_fetched_date, + fqn, + summary_html +FROM users; +DROP TABLE users; +ALTER TABLE users_before_themes RENAME TO users; diff --git a/migrations/sqlite/2019-06-21-154916_themes/up.sql b/migrations/sqlite/2019-06-21-154916_themes/up.sql new file mode 100644 index 00000000..5a92b2a0 --- /dev/null +++ b/migrations/sqlite/2019-06-21-154916_themes/up.sql @@ -0,0 +1,4 @@ +-- Your SQL goes here +ALTER TABLE blogs ADD COLUMN theme VARCHAR; +ALTER TABLE users ADD COLUMN preferred_theme VARCHAR; +ALTER TABLE users ADD COLUMN hide_custom_css BOOLEAN NOT NULL DEFAULT 'f'; diff --git a/plume-models/Cargo.toml b/plume-models/Cargo.toml index 436d67b4..46e4e3ae 100644 --- a/plume-models/Cargo.toml +++ b/plume-models/Cargo.toml @@ -23,6 +23,7 @@ serde_derive = "1.0" serde_json = "1.0" tantivy = "0.10.1" url = "2.1" +walkdir = "2.2" webfinger = "0.4.1" whatlang = "0.7.1" shrinkwraprs = "0.2.1" diff --git a/plume-models/src/blogs.rs b/plume-models/src/blogs.rs index 8c55f402..2adfabc6 100644 --- a/plume-models/src/blogs.rs +++ b/plume-models/src/blogs.rs @@ -44,6 +44,7 @@ pub struct Blog { pub summary_html: SafeString, pub icon_id: Option, pub banner_id: Option, + pub theme: Option, } #[derive(Default, Insertable)] @@ -61,6 +62,7 @@ pub struct NewBlog { pub summary_html: SafeString, pub icon_id: Option, pub banner_id: Option, + pub theme: Option, } const BLOG_PREFIX: &str = "~"; @@ -272,7 +274,7 @@ impl Blog { pub fn icon_url(&self, conn: &Connection) -> String { self.icon_id .and_then(|id| Media::get(conn, id).and_then(|m| m.url()).ok()) - .unwrap_or_else(|| "/static/default-avatar.png".to_string()) + .unwrap_or_else(|| "/static/images/default-avatar.png".to_string()) } pub fn banner_url(&self, conn: &Connection) -> Option { @@ -392,6 +394,7 @@ impl FromId for Blog { .summary_string() .unwrap_or_default(), ), + theme: None, }, ) } diff --git a/plume-models/src/config.rs b/plume-models/src/config.rs index 493fdcd9..41a989c1 100644 --- a/plume-models/src/config.rs +++ b/plume-models/src/config.rs @@ -14,6 +14,7 @@ pub struct Config { pub search_index: String, pub rocket: Result, pub logo: LogoConfig, + pub default_theme: String, } #[derive(Debug, Clone)] @@ -199,5 +200,6 @@ lazy_static! { search_index: var("SEARCH_INDEX").unwrap_or_else(|_| "search_index".to_owned()), rocket: get_rocket_config(), logo: LogoConfig::default(), + default_theme: var("DEFAULT_THEME").unwrap_or_else(|_| "default-light".to_owned()), }; } diff --git a/plume-models/src/instance.rs b/plume-models/src/instance.rs index 003456c8..8e071689 100644 --- a/plume-models/src/instance.rs +++ b/plume-models/src/instance.rs @@ -186,6 +186,60 @@ impl Instance { .get_result(conn) .map_err(Error::from) } + + /// Returns a list of the local instance themes (all files matching `static/css/NAME/theme.css`) + /// + /// The list only contains the name of the themes, without their extension or full path. + pub fn list_themes() -> Result> { + // List all the files in static/css + std::path::Path::new("static") + .join("css") + .read_dir() + .map(|files| { + files + .filter_map(std::result::Result::ok) + // Only keep actual directories (each theme has its own dir) + .filter(|f| f.file_type().map(|t| t.is_dir()).unwrap_or(false)) + // Only keep the directory name (= theme name) + .filter_map(|f| { + f.path() + .file_name() + .and_then(std::ffi::OsStr::to_str) + .map(std::borrow::ToOwned::to_owned) + }) + // Ignore the one starting with "blog-": these are the blog themes + .filter(|f| !f.starts_with("blog-")) + .collect() + }) + .map_err(Error::from) + } + + /// Returns a list of the local blog themes (all files matching `static/css/blog-NAME/theme.css`) + /// + /// The list only contains the name of the themes, without their extension or full path. + pub fn list_blog_themes() -> Result> { + // List all the files in static/css + std::path::Path::new("static") + .join("css") + .read_dir() + .map(|files| { + files + .filter_map(std::result::Result::ok) + // Only keep actual directories (each theme has its own dir) + .filter(|f| f.file_type().map(|t| t.is_dir()).unwrap_or(false)) + // Only keep the directory name (= theme name) + .filter_map(|f| { + f.path() + .file_name() + .and_then(std::ffi::OsStr::to_str) + .map(std::borrow::ToOwned::to_owned) + }) + // Only keep the one starting with "blog-": these are the blog themes + .filter(|f| f.starts_with("blog-")) + .collect() + }) + .map_err(Error::from) + } } #[cfg(test)] diff --git a/plume-models/src/lib.rs b/plume-models/src/lib.rs index 2c30cb8b..23bb5fc7 100644 --- a/plume-models/src/lib.rs +++ b/plume-models/src/lib.rs @@ -33,6 +33,7 @@ extern crate serde_json; #[macro_use] extern crate tantivy; extern crate url; +extern crate walkdir; extern crate webfinger; extern crate whatlang; diff --git a/plume-models/src/schema.rs b/plume-models/src/schema.rs index f2cc833c..2d518fd0 100644 --- a/plume-models/src/schema.rs +++ b/plume-models/src/schema.rs @@ -47,6 +47,7 @@ table! { summary_html -> Text, icon_id -> Nullable, banner_id -> Nullable, + theme -> Nullable, } } @@ -216,6 +217,8 @@ table! { last_fetched_date -> Timestamp, fqn -> Text, summary_html -> Text, + preferred_theme -> Nullable, + hide_custom_css -> Bool, } } diff --git a/plume-models/src/users.rs b/plume-models/src/users.rs index 4b1d3a54..c30215c7 100644 --- a/plume-models/src/users.rs +++ b/plume-models/src/users.rs @@ -73,6 +73,8 @@ pub struct User { pub last_fetched_date: NaiveDateTime, pub fqn: String, pub summary_html: SafeString, + pub preferred_theme: Option, + pub hide_custom_css: bool, } #[derive(Default, Insertable)] @@ -202,30 +204,6 @@ impl User { .map_err(Error::from) } - pub fn update( - &self, - conn: &Connection, - name: String, - email: String, - summary: String, - ) -> Result { - diesel::update(self) - .set(( - users::display_name.eq(name), - users::email.eq(email), - users::summary_html.eq(utils::md_to_html( - &summary, - None, - false, - Some(Media::get_media_processor(conn, vec![self])), - ) - .0), - users::summary.eq(summary), - )) - .execute(conn)?; - User::get(conn, self.id) - } - pub fn count_local(conn: &Connection) -> Result { users::table .filter(users::instance_id.eq(Instance::get_local()?.id)) @@ -668,7 +646,7 @@ impl User { pub fn avatar_url(&self, conn: &Connection) -> String { self.avatar_id .and_then(|id| Media::get(conn, id).and_then(|m| m.url()).ok()) - .unwrap_or_else(|| "/static/default-avatar.png".to_string()) + .unwrap_or_else(|| "/static/images/default-avatar.png".to_string()) } pub fn webfinger(&self, conn: &Connection) -> Result { @@ -1076,27 +1054,6 @@ pub(crate) mod tests { }); } - #[test] - fn update() { - let conn = &db(); - conn.test_transaction::<_, (), _>(|| { - let inserted = fill_database(conn); - let updated = inserted[0] - .update( - conn, - "new name".to_owned(), - "em@il".to_owned(), - "

summary

".to_owned(), - ) - .unwrap(); - assert_eq!(updated.display_name, "new name"); - assert_eq!(updated.email.unwrap(), "em@il"); - assert_eq!(updated.summary_html.get(), "

summary

"); - - Ok(()) - }); - } - #[test] fn auth() { let conn = &db(); diff --git a/src/main.rs b/src/main.rs index 0bdfaddc..c2e545cf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -238,6 +238,7 @@ Then try to restart Plume routes::session::password_reset_request, routes::session::password_reset_form, routes::session::password_reset, + routes::theme_files, routes::plume_static_files, routes::static_files, routes::tags::tag, diff --git a/src/routes/blogs.rs b/src/routes/blogs.rs index 7ab9e2b3..8ae69084 100644 --- a/src/routes/blogs.rs +++ b/src/routes/blogs.rs @@ -181,6 +181,7 @@ pub struct EditForm { pub summary: String, pub icon: Option, pub banner: Option, + pub theme: Option, } #[get("/~//edit")] @@ -207,6 +208,7 @@ pub fn edit(name: String, rockets: PlumeRocket) -> Result { summary: blog.summary.clone(), icon: blog.icon_id, banner: blog.banner_id, + theme: blog.theme.clone(), }, ValidationErrors::default() ))) @@ -318,6 +320,7 @@ pub fn update( ); blog.icon_id = form.icon; blog.banner_id = form.banner; + blog.theme = form.theme.clone(); blog.save_changes::(&*conn) .expect("Couldn't save blog changes"); Ok(Flash::success( diff --git a/src/routes/mod.rs b/src/routes/mod.rs index c29ab10f..cb9cfc33 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -2,15 +2,20 @@ use atom_syndication::{ContentBuilder, Entry, EntryBuilder, LinkBuilder, Person, PersonBuilder}; use rocket::{ http::{ - hyper::header::{CacheControl, CacheDirective}, + hyper::header::{CacheControl, CacheDirective, ETag, EntityTag}, uri::{FromUriParam, Query}, RawStr, Status, }, request::{self, FromFormValue, FromRequest, Request}, - response::{Flash, NamedFile, Redirect}, + response::{self, Flash, NamedFile, Redirect, Responder, Response}, Outcome, }; -use std::path::{Path, PathBuf}; +use std::{ + collections::hash_map::DefaultHasher, + hash::Hasher, + io::Read, + path::{Path, PathBuf}, +}; use template_utils::Ructe; use plume_models::{posts::Post, Connection}; @@ -168,6 +173,44 @@ pub struct CachedFile { cache_control: CacheControl, } +#[derive(Debug)] +pub struct ThemeFile(NamedFile); + +impl<'r> Responder<'r> for ThemeFile { + fn respond_to(mut self, r: &Request) -> response::Result<'r> { + let mut contents = String::new(); + self.0 + .read_to_string(&mut contents) + .map_err(|_| Status::InternalServerError)?; + + let mut hasher = DefaultHasher::new(); + hasher.write(&contents.as_bytes()); + let etag = format!("{:x}", hasher.finish()); + + if r.headers() + .get("If-None-Match") + .any(|s| s[1..s.len() - 1] == etag) + { + Response::build() + .status(Status::NotModified) + .header(ETag(EntityTag::strong(etag))) + .ok() + } else { + Response::build() + .merge(self.0.respond_to(r)?) + .header(ETag(EntityTag::strong(etag))) + .ok() + } + } +} + +#[get("/static/cached/<_build_id>/css/", rank = 1)] +pub fn theme_files(file: PathBuf, _build_id: &RawStr) -> Option { + NamedFile::open(Path::new("static/").join(file)) + .ok() + .map(ThemeFile) +} + #[get("/static/cached/<_build_id>/", rank = 2)] pub fn plume_static_files(file: PathBuf, _build_id: &RawStr) -> Option { static_files(file) diff --git a/src/routes/user.rs b/src/routes/user.rs index b2316cb7..70b8699e 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -1,5 +1,6 @@ use activitypub::{activity::Create, collection::OrderedCollection}; use atom_syndication::{Entry, FeedBuilder}; +use diesel::SaveChangesDsl; use rocket::{ http::{ContentType, Cookies}, request::LenientForm, @@ -20,8 +21,10 @@ use plume_models::{ headers::Headers, inbox::inbox as local_inbox, instance::Instance, + medias::Media, posts::{LicensedArticle, Post}, reshares::Reshare, + safe_string::SafeString, users::*, Error, PlumeRocket, }; @@ -342,7 +345,9 @@ pub fn edit(name: String, user: User, rockets: PlumeRocket) -> Result, + pub hide_custom_css: bool, } #[put("/@/<_name>/edit", data = "
")] pub fn update( _name: String, conn: DbConn, - user: User, + mut user: User, form: LenientForm, intl: I18n, ) -> Result, ErrorPage> { - user.update( - &*conn, - if !form.display_name.is_empty() { - form.display_name.clone() - } else { - user.display_name.clone() - }, - if !form.email.is_empty() { - form.email.clone() - } else { - user.email.clone().unwrap_or_default() - }, - if !form.summary.is_empty() { - form.summary.clone() - } else { - user.summary.to_string() - }, - )?; + user.display_name = form.display_name.clone(); + user.email = Some(form.email.clone()); + user.summary = form.summary.clone(); + user.summary_html = SafeString::new( + &utils::md_to_html( + &form.summary, + None, + false, + Some(Media::get_media_processor(&conn, vec![&user])), + ) + .0, + ); + user.preferred_theme = form.theme.clone(); + user.hide_custom_css = form.hide_custom_css; + let _: User = user.save_changes(&*conn).map_err(Error::from)?; + Ok(Flash::success( Redirect::to(uri!(me)), i18n!(intl.catalog, "Your profile has been updated."), diff --git a/static/css/main.scss b/static/css/main.scss deleted file mode 100644 index 1615854f..00000000 --- a/static/css/main.scss +++ /dev/null @@ -1,175 +0,0 @@ -/* color palette: https://coolors.co/23f0c7-ef767a-7765e3-6457a6-ffe347 */ - -@import url('../fonts/Route159/Route159.css'); -@import url('../fonts/Lora/Lora.css'); -@import url('../fonts/Playfair_Display/PlayfairDisplay.css'); - -html { - box-sizing: border-box; -} -*, *:before, *:after { - box-sizing: inherit; -} - -@import 'variables'; -@import 'global'; -@import 'header'; -@import 'article'; -@import 'forms'; - -/// Small screens -@media screen and (max-width: 600px) { - @keyframes menuOpening { - from { - transform: scaleX(0); - transform-origin: left; - opacity: 0; - } - to { - transform: scaleX(1); - transform-origin: left; - opacity: 1; - } - } - - body > header { - flex-direction: column; - - nav#menu { - display: inline-flex; - z-index: 21; - } - - #content { - display: none; - appearance: none; - text-align: center; - z-index: 20; - } - } - - body > header:focus-within #content, #content.show { - position: fixed; - display: flex; - flex-direction: column; - justify-content: flex-start; - - top: 0; - left: 0; - width: 100%; - height: 100%; - box-sizing: border-box; - - animation: 0.2s menuOpening; - - &::before { - content: ""; - position: absolute; - transform: skewX(-10deg); - top: 0; - left: -20%; - width: 100%; - height: 100%; - - z-index: -10; - - background: $purple; - } - - > nav { - flex-direction: column; - align-items: flex-start; - - a { - display: flex; - flex-direction: row; - align-items: center; - margin: 0; - padding: 1rem 1.5rem; - color: $white; - font-size: 1.4em; - font-weight: 300; - - &.title { font-size: 1.8em; } - - > *:first-child { width: 3rem; } - > img:first-child { height: 3rem; } - > *:last-child { margin-left: 1rem; } - > nav hr { - display: block; - margin: 0; - width: 100%; - border: solid $white 0.1rem; - } - .mobile-label { display: initial; } - } - } - } - - main .article-meta { - > *, .comments { - margin: 0 5%; - } - > p { - margin: 2em 5%; - font-size: 0.9em; - } - .comments > * { margin: auto 5%; } - .comments .comment { padding: 2em 0px; } - } - main .article-info, main article, main h1.article, main h2.article { - max-width: 90vw; - } - - .card { - min-width: 80%; - min-height: 80%; - } - - .tabs { - margin: auto 0px 2em; - } - - .stats { flex-direction: column; } - body > footer { - flex-direction: column; - align-items: center; - } - body > footer * { - margin: 1em auto; - text-align: center; - } - - .flex.wrap { flex-direction: column; } - - .cards, .list { - margin: 1rem 0 5rem; - } - - .split { - flex-direction: column; - margin: 0; - - & > * { - max-width: 100%; - } - } - - .bottom-bar { - flex-direction: column; - align-items: center; - & > div { - margin: 0; - } - } - - main .article-meta .comments .comment { - header { - flex-direction: column; - } - - .content { - margin-top: 0.5em; - } - } -} diff --git a/static/media/.gitkeep b/static/media/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/templates/base.rs.html b/templates/base.rs.html index d184b574..d8a74e49 100644 --- a/templates/base.rs.html +++ b/templates/base.rs.html @@ -2,16 +2,16 @@ @use plume_models::instance::Instance; @use template_utils::*; @use routes::*; +@use std::path::Path; @(ctx: BaseContext, title: String, head: Content, header: Content, content: Content) - + @title ⋅ @i18n!(ctx.1, "Plume") - - + diff --git a/templates/blogs/details.rs.html b/templates/blogs/details.rs.html index 71c87a71..30974f29 100644 --- a/templates/blogs/details.rs.html +++ b/templates/blogs/details.rs.html @@ -5,6 +5,7 @@ @use templates::{base, partials::post_card}; @use template_utils::*; @use routes::*; +@use std::path::Path; @(ctx: BaseContext, blog: Blog, authors: &[User], page: i32, n_pages: i32, posts: Vec) @@ -23,6 +24,11 @@ + @if !ctx.2.clone().map(|u| u.hide_custom_css).unwrap_or(false) { + @if let Some(ref theme) = blog.theme { + + } + } }, { @blog.title }, { diff --git a/templates/blogs/edit.rs.html b/templates/blogs/edit.rs.html index dfa7f44f..0b1febbf 100644 --- a/templates/blogs/edit.rs.html +++ b/templates/blogs/edit.rs.html @@ -1,5 +1,6 @@ @use validator::ValidationErrors; @use plume_models::blogs::Blog; +@use plume_models::instance::Instance; @use plume_models::medias::Media; @use routes::blogs; @use routes::blogs::EditForm; @@ -31,6 +32,18 @@ @:image_select(ctx, "icon", i18n!(ctx.1, "Blog icon"), true, medias.clone(), form.icon) @:image_select(ctx, "banner", i18n!(ctx.1, "Blog banner"), true, medias, form.banner) + @if let Ok(themes) = Instance::list_themes() { + + + } else { +

@i18n!(ctx.1, "Error while loading theme selector.")

+ } + diff --git a/templates/instance/admin.rs.html b/templates/instance/admin.rs.html index fcf6f6eb..50bde423 100644 --- a/templates/instance/admin.rs.html +++ b/templates/instance/admin.rs.html @@ -20,12 +20,9 @@ @input!(ctx.1, name (text), "Name", form, errors.clone(), "props") diff --git a/templates/posts/details.rs.html b/templates/posts/details.rs.html index f8a0803f..7a67b40c 100644 --- a/templates/posts/details.rs.html +++ b/templates/posts/details.rs.html @@ -8,6 +8,7 @@ @use validator::ValidationErrors; @use routes::comments::NewCommentForm; @use routes::*; +@use std::path::Path; @(ctx: BaseContext, article: Post, blog: Blog, comment_form: &NewCommentForm, comment_errors: ValidationErrors, tags: Vec, comments: Vec, previous_comment: Option, n_likes: i64, n_reshares: i64, has_liked: bool, has_reshared: bool, is_following: bool, author: User) @@ -19,6 +20,12 @@ } + + @if !ctx.2.clone().map(|u| u.hide_custom_css).unwrap_or(false) { + @if let Some(ref theme) = blog.theme { + + } + } }, { @blog.title }, { diff --git a/templates/users/edit.rs.html b/templates/users/edit.rs.html index 86777e42..7dce82bd 100644 --- a/templates/users/edit.rs.html +++ b/templates/users/edit.rs.html @@ -1,5 +1,6 @@ @use templates::base; @use template_utils::*; +@use plume_models::instance::Instance; @use routes::user::UpdateUserForm; @use validator::ValidationErrors; @use routes::*; @@ -22,6 +23,23 @@ + @if let Ok(themes) = Instance::list_themes() { + + + } else { +

@i18n!(ctx.1, "Error while loading theme selector.")

+ } + + +