Style rework #35
49 changed files with 1322 additions and 802 deletions
1
.gitattributes
vendored
1
.gitattributes
vendored
|
@ -1,3 +1,4 @@
|
||||||
*.png filter=lfs diff=lfs merge=lfs -text
|
*.png filter=lfs diff=lfs merge=lfs -text
|
||||||
*.gif filter=lfs diff=lfs merge=lfs -text
|
*.gif filter=lfs diff=lfs merge=lfs -text
|
||||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.webp filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|
74
Cargo.lock
generated
74
Cargo.lock
generated
|
@ -256,6 +256,12 @@ dependencies = [
|
||||||
"alloc-no-stdlib",
|
"alloc-no-stdlib",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "allocator-api2"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android-tzdata"
|
name = "android-tzdata"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -476,15 +482,16 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cached"
|
name = "cached"
|
||||||
version = "0.45.1"
|
version = "0.46.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "90eb5776f28a149524d1d8623035760b4454ec881e8cf3838fa8d7e1b11254b3"
|
checksum = "8cead8ece0da6b744b2ad8ef9c58a4cdc7ef2921e60a6ddfb9eaaa86839b5fc5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"cached_proc_macro",
|
"cached_proc_macro",
|
||||||
"cached_proc_macro_types",
|
"cached_proc_macro_types",
|
||||||
"futures",
|
"futures",
|
||||||
"hashbrown 0.13.2",
|
"hashbrown 0.14.1",
|
||||||
"instant",
|
"instant",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
@ -611,11 +618,12 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "comrak"
|
name = "comrak"
|
||||||
version = "0.18.0"
|
version = "0.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "482aa5695bca086022be453c700a40c02893f1ba7098a2c88351de55341ae894"
|
checksum = "82c995deda3bfdebd07d0e2af79e9da13e4b1be652b21a746f3f5b24bf0a49ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
|
"derive_builder",
|
||||||
"entities",
|
"entities",
|
||||||
"memchr",
|
"memchr",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
@ -696,7 +704,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "874c6e2d19f8d4a285083b11a3241bfbe01ac3ed85f26e1e6b34888d960552bd"
|
checksum = "874c6e2d19f8d4a285083b11a3241bfbe01ac3ed85f26e1e6b34888d960552bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"indexmap",
|
"indexmap 1.9.3",
|
||||||
"nom",
|
"nom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -819,6 +827,12 @@ version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca"
|
checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equivalent"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -1020,7 +1034,7 @@ dependencies = [
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
"indexmap",
|
"indexmap 1.9.3",
|
||||||
"slab",
|
"slab",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
|
@ -1043,6 +1057,16 @@ dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"allocator-api2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -1208,6 +1232,16 @@ dependencies = [
|
||||||
"hashbrown 0.12.3",
|
"hashbrown 0.12.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown 0.14.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "instant"
|
name = "instant"
|
||||||
version = "0.1.12"
|
version = "0.1.12"
|
||||||
|
@ -1708,7 +1742,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9bd9647b268a3d3e14ff09c23201133a62589c658db02bb7388c7246aafe0590"
|
checksum = "9bd9647b268a3d3e14ff09c23201133a62589c658db02bb7388c7246aafe0590"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"indexmap",
|
"indexmap 1.9.3",
|
||||||
"line-wrap",
|
"line-wrap",
|
||||||
"quick-xml",
|
"quick-xml",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -2058,9 +2092,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_spanned"
|
name = "serde_spanned"
|
||||||
version = "0.6.2"
|
version = "0.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d"
|
checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
@ -2083,7 +2117,7 @@ version = "0.9.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9d684e3ec7de3bf5466b32bd75303ac16f0736426e5a4e0d6e489559ce1249c"
|
checksum = "d9d684e3ec7de3bf5466b32bd75303ac16f0736426e5a4e0d6e489559ce1249c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap 1.9.3",
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -2358,9 +2392,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.7.4"
|
version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec"
|
checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_spanned",
|
"serde_spanned",
|
||||||
|
@ -2370,20 +2404,20 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.6.2"
|
version = "0.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f"
|
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
version = "0.19.9"
|
version = "0.20.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "92d964908cec0d030b812013af25a0e57fddfadb1e066ecc6681d86253129d4f"
|
checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap 2.0.2",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_spanned",
|
"serde_spanned",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
|
@ -2803,9 +2837,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.4.6"
|
version = "0.5.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699"
|
checksum = "037711d82167854aff2018dfd193aa0fef5370f456732f0d5a0c59b0f1b4b907"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
|
@ -12,15 +12,15 @@ license = "AGPL-3.0-or-later"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "4.4"
|
actix-web = "4.4"
|
||||||
actix-files = "0.6"
|
actix-files = "0.6"
|
||||||
cached = { version = "0.45", features = ["async"] }
|
cached = { version = "0.46", features = ["async"] }
|
||||||
ramhorns = "0.14"
|
ramhorns = "0.14"
|
||||||
toml = "0.7"
|
toml = "0.8"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_yaml = "0.9"
|
serde_yaml = "0.9"
|
||||||
minify-html = "0.11"
|
minify-html = "0.11"
|
||||||
minify-js = "0.5"
|
minify-js = "0.5"
|
||||||
glob = "0.3"
|
glob = "0.3"
|
||||||
comrak = "0.18"
|
comrak = "0.19"
|
||||||
reqwest = { version = "0.11", features = ["json"] }
|
reqwest = { version = "0.11", features = ["json"] }
|
||||||
chrono = "0.4.30"
|
chrono = "0.4.30"
|
||||||
chrono-tz = "0.8"
|
chrono-tz = "0.8"
|
||||||
|
|
|
@ -82,7 +82,7 @@ onion = "http://youraddress.onion/"
|
||||||
## Example of [`config.toml`](./config/config.toml)
|
## Example of [`config.toml`](./config/config.toml)
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
mail = your.mail at host.com"
|
mail = "your.mail at host.com"
|
||||||
lang = "lang"
|
lang = "lang"
|
||||||
onion = "http://youraddress.onion/"
|
onion = "http://youraddress.onion/"
|
||||||
app_name = "Nickname"
|
app_name = "Nickname"
|
||||||
|
|
|
@ -124,6 +124,7 @@ fn init(dist_dir: String, static_dir: String, templates_dir: String) -> String {
|
||||||
keep_closing_tags: true,
|
keep_closing_tags: true,
|
||||||
minify_css: true,
|
minify_css: true,
|
||||||
minify_js: true,
|
minify_js: true,
|
||||||
|
remove_bangs: false,
|
||||||
..minify_html::Cfg::spec_compliant()
|
..minify_html::Cfg::spec_compliant()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
18
src/main.rs
18
src/main.rs
|
@ -3,7 +3,7 @@ use actix_web::{middleware::DefaultHeaders, web, App, HttpServer};
|
||||||
use std::io::Result;
|
use std::io::Result;
|
||||||
|
|
||||||
use crate::routes::{
|
use crate::routes::{
|
||||||
agreements, api_v1, blog, contrib, cours, cv, gaming, index, memorial, networks, not_found,
|
agreements, api_v1, blog, contact, contrib, cours, cv, gaming, index, memorial, not_found,
|
||||||
portfolio, setup, web3,
|
portfolio, setup, web3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,10 +29,15 @@ async fn main() -> Result<()> {
|
||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
App::new()
|
App::new()
|
||||||
.app_data(web::Data::new(config.to_owned()))
|
.app_data(web::Data::new(config.to_owned()))
|
||||||
.wrap(DefaultHeaders::new().add((
|
.wrap(
|
||||||
"Onion-Location",
|
DefaultHeaders::new()
|
||||||
config.fc.onion.as_deref().unwrap_or_default(),
|
.add((
|
||||||
)))
|
"Onion-Location",
|
||||||
|
config.fc.onion.as_deref().unwrap_or_default(),
|
||||||
|
))
|
||||||
|
.add(("Server", format!("ewp/{}", env!("CARGO_PKG_VERSION"))))
|
||||||
|
.add(("Permissions-Policy", "interest-cohort=()")),
|
||||||
|
)
|
||||||
.service(web::scope("/api").service(web::scope("v1").service(api_v1::love)))
|
.service(web::scope("/api").service(web::scope("v1").service(api_v1::love)))
|
||||||
.service(index::page)
|
.service(index::page)
|
||||||
.service(agreements::security)
|
.service(agreements::security)
|
||||||
|
@ -47,7 +52,8 @@ async fn main() -> Result<()> {
|
||||||
.service(cv::page)
|
.service(cv::page)
|
||||||
.service(gaming::page)
|
.service(gaming::page)
|
||||||
.service(memorial::page)
|
.service(memorial::page)
|
||||||
.service(networks::page)
|
.service(contact::page)
|
||||||
|
.service(contact::service_redirection)
|
||||||
.service(portfolio::page)
|
.service(portfolio::page)
|
||||||
.service(setup::page)
|
.service(setup::page)
|
||||||
.service(web3::page)
|
.service(web3::page)
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
use crate::misc::date::Date;
|
use crate::misc::date::Date;
|
||||||
use comrak::nodes::{AstNode, NodeValue};
|
use comrak::nodes::{AstNode, NodeValue};
|
||||||
use comrak::{
|
use comrak::{format_html, parse_document, Arena, ComrakOptions, ListStyleType};
|
||||||
format_html, parse_document, Arena, ComrakExtensionOptions, ComrakOptions, ComrakParseOptions,
|
|
||||||
ComrakRenderOptions, ListStyleType,
|
|
||||||
};
|
|
||||||
use ramhorns::Content;
|
use ramhorns::Content;
|
||||||
use serde::{Deserialize, Deserializer};
|
use serde::{Deserialize, Deserializer};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
@ -17,6 +14,7 @@ pub struct FileMetadata {
|
||||||
pub publish: Option<bool>,
|
pub publish: Option<bool>,
|
||||||
pub tags: Option<Vec<Tag>>,
|
pub tags: Option<Vec<Tag>>,
|
||||||
pub toc: Option<bool>,
|
pub toc: Option<bool>,
|
||||||
|
pub language: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Content, Debug, Clone)]
|
#[derive(Content, Debug, Clone)]
|
||||||
|
@ -55,39 +53,41 @@ pub struct File {
|
||||||
|
|
||||||
/// Options used for parser and compiler MD --> HTML
|
/// Options used for parser and compiler MD --> HTML
|
||||||
pub fn get_options() -> ComrakOptions {
|
pub fn get_options() -> ComrakOptions {
|
||||||
ComrakOptions {
|
let mut options = comrak::Options::default();
|
||||||
extension: ComrakExtensionOptions {
|
|
||||||
strikethrough: true,
|
// Extension
|
||||||
tagfilter: true,
|
options.extension.strikethrough = true;
|
||||||
table: true,
|
options.extension.tagfilter = true;
|
||||||
autolink: true,
|
options.extension.table = true;
|
||||||
tasklist: true,
|
options.extension.autolink = true;
|
||||||
superscript: true,
|
options.extension.tasklist = true;
|
||||||
header_ids: Some(String::new()),
|
options.extension.superscript = true;
|
||||||
footnotes: true,
|
options.extension.header_ids = Some(String::new());
|
||||||
description_lists: true,
|
options.extension.footnotes = true;
|
||||||
front_matter_delimiter: Some("---".into()),
|
options.extension.description_lists = true;
|
||||||
},
|
options.extension.front_matter_delimiter = Some("---".into());
|
||||||
parse: ComrakParseOptions {
|
|
||||||
smart: true, // could be boring
|
// Parser
|
||||||
default_info_string: Some("plaintext".into()),
|
options.parse.smart = true; // could be boring
|
||||||
relaxed_tasklist_matching: true,
|
options.parse.default_info_string = Some("plaintext".into());
|
||||||
},
|
options.parse.relaxed_tasklist_matching = true;
|
||||||
render: ComrakRenderOptions {
|
options.parse.relaxed_autolinks = true;
|
||||||
hardbreaks: false, // could be true? change by metadata could be good for compatibility
|
|
||||||
github_pre_lang: false,
|
// Renderer
|
||||||
full_info_string: true,
|
options.render.hardbreaks = false; // could be true? change by metadata could be good for compatibility
|
||||||
width: 0, // 0 mean disabled?
|
options.render.github_pre_lang = false;
|
||||||
unsafe_: true,
|
options.render.full_info_string = true;
|
||||||
escape: false,
|
options.render.width = 0; // 0 mean disabled?
|
||||||
list_style: ListStyleType::Dash,
|
options.render.unsafe_ = true;
|
||||||
sourcepos: false,
|
options.render.escape = false;
|
||||||
},
|
options.render.list_style = ListStyleType::Dash;
|
||||||
}
|
options.render.sourcepos = false;
|
||||||
|
|
||||||
|
options
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transform markdown string to File structure
|
/// Transform markdown string to File structure
|
||||||
pub fn read(raw_text: &str) -> File {
|
fn read(raw_text: &str) -> File {
|
||||||
let arena = Arena::new();
|
let arena = Arena::new();
|
||||||
|
|
||||||
let options = get_options();
|
let options = get_options();
|
||||||
|
|
|
@ -6,7 +6,7 @@ use ramhorns::Content;
|
||||||
#[routes]
|
#[routes]
|
||||||
#[get("/.well-known/security.txt")]
|
#[get("/.well-known/security.txt")]
|
||||||
#[get("/security.txt")]
|
#[get("/security.txt")]
|
||||||
pub async fn security(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
async fn security(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
||||||
HttpResponse::Ok().body(build_securitytxt(
|
HttpResponse::Ok().body(build_securitytxt(
|
||||||
config.get_ref().to_owned(),
|
config.get_ref().to_owned(),
|
||||||
get_url(req.connection_info()),
|
get_url(req.connection_info()),
|
||||||
|
@ -34,7 +34,7 @@ fn build_securitytxt(config: Config, url: String) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/humans.txt")]
|
#[get("/humans.txt")]
|
||||||
pub async fn humans(config: web::Data<Config>) -> impl Responder {
|
async fn humans(config: web::Data<Config>) -> impl Responder {
|
||||||
HttpResponse::Ok().body(build_humanstxt(config.get_ref().to_owned()))
|
HttpResponse::Ok().body(build_humanstxt(config.get_ref().to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ fn build_humanstxt(config: Config) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/robots.txt")]
|
#[get("/robots.txt")]
|
||||||
pub async fn robots() -> impl Responder {
|
async fn robots() -> impl Responder {
|
||||||
HttpResponse::Ok().body(build_robotstxt())
|
HttpResponse::Ok().body(build_robotstxt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ fn build_robotstxt() -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/sitemap.xml")]
|
#[get("/sitemap.xml")]
|
||||||
pub async fn sitemap() -> impl Responder {
|
async fn sitemap() -> impl Responder {
|
||||||
// TODO
|
// TODO
|
||||||
actix_web::web::Redirect::to("/")
|
actix_web::web::Redirect::to("/")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ struct Info {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/love")]
|
#[get("/love")]
|
||||||
pub async fn love() -> impl Responder {
|
async fn love() -> impl Responder {
|
||||||
HttpResponse::Ok().json(Info {
|
HttpResponse::Ok().json(Info {
|
||||||
unix_epoch: 1605576600,
|
unix_epoch: 1605576600,
|
||||||
})
|
})
|
||||||
|
|
|
@ -21,13 +21,13 @@ use crate::{
|
||||||
markdown::{get_metadata, get_options, read_file, File, FileMetadata},
|
markdown::{get_metadata, get_options, read_file, File, FileMetadata},
|
||||||
utils::get_url,
|
utils::get_url,
|
||||||
},
|
},
|
||||||
template::Infos,
|
template::{Infos, NavBar},
|
||||||
};
|
};
|
||||||
|
|
||||||
const MIME_TYPE_RSS: &str = "application/rss+xml";
|
const MIME_TYPE_RSS: &str = "application/rss+xml";
|
||||||
|
|
||||||
#[get("/blog")]
|
#[get("/blog")]
|
||||||
pub async fn index(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
async fn index(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
||||||
HttpResponse::Ok().body(build_index(
|
HttpResponse::Ok().body(build_index(
|
||||||
config.get_ref().to_owned(),
|
config.get_ref().to_owned(),
|
||||||
get_url(req.connection_info()),
|
get_url(req.connection_info()),
|
||||||
|
@ -36,12 +36,13 @@ pub async fn index(req: HttpRequest, config: web::Data<Config>) -> impl Responde
|
||||||
|
|
||||||
#[derive(Content, Debug)]
|
#[derive(Content, Debug)]
|
||||||
struct BlogIndexTemplate {
|
struct BlogIndexTemplate {
|
||||||
|
navbar: NavBar,
|
||||||
posts: Vec<Post>,
|
posts: Vec<Post>,
|
||||||
no_posts: bool,
|
no_posts: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[once(time = 120)]
|
#[once(time = 120)]
|
||||||
pub fn build_index(config: Config, url: String) -> String {
|
fn build_index(config: Config, url: String) -> String {
|
||||||
let mut posts = get_posts("data/blog");
|
let mut posts = get_posts("data/blog");
|
||||||
|
|
||||||
// Sort from newest to oldest
|
// Sort from newest to oldest
|
||||||
|
@ -51,6 +52,10 @@ pub fn build_index(config: Config, url: String) -> String {
|
||||||
config.tmpl.render(
|
config.tmpl.render(
|
||||||
"blog/index.html",
|
"blog/index.html",
|
||||||
BlogIndexTemplate {
|
BlogIndexTemplate {
|
||||||
|
navbar: NavBar {
|
||||||
|
blog: true,
|
||||||
|
..NavBar::default()
|
||||||
|
},
|
||||||
no_posts: posts.is_empty(),
|
no_posts: posts.is_empty(),
|
||||||
posts,
|
posts,
|
||||||
},
|
},
|
||||||
|
@ -172,12 +177,13 @@ fn get_posts(location: &str) -> Vec<Post> {
|
||||||
|
|
||||||
#[derive(Content, Debug)]
|
#[derive(Content, Debug)]
|
||||||
struct BlogPostTemplate {
|
struct BlogPostTemplate {
|
||||||
|
navbar: NavBar,
|
||||||
post: Option<File>,
|
post: Option<File>,
|
||||||
toc: String,
|
toc: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/blog/p/{id}")]
|
#[get("/blog/p/{id}")]
|
||||||
pub async fn page(
|
async fn page(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
path: web::Path<(String,)>,
|
path: web::Path<(String,)>,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
|
@ -193,9 +199,18 @@ fn build_post(file: String, config: Config, url: String) -> String {
|
||||||
let mut post = None;
|
let mut post = None;
|
||||||
let (infos, toc) = get_post(&mut post, file, config.fc.name.unwrap_or_default(), url);
|
let (infos, toc) = get_post(&mut post, file, config.fc.name.unwrap_or_default(), url);
|
||||||
|
|
||||||
config
|
config.tmpl.render(
|
||||||
.tmpl
|
"blog/post.html",
|
||||||
.render("blog/post.html", BlogPostTemplate { post, toc }, infos)
|
BlogPostTemplate {
|
||||||
|
navbar: NavBar {
|
||||||
|
blog: true,
|
||||||
|
..NavBar::default()
|
||||||
|
},
|
||||||
|
post,
|
||||||
|
toc,
|
||||||
|
},
|
||||||
|
infos,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_post(
|
fn get_post(
|
||||||
|
@ -234,7 +249,7 @@ fn get_post(
|
||||||
page_title: Some(format!("Post: {}", title)),
|
page_title: Some(format!("Post: {}", title)),
|
||||||
page_desc: Some(format!("Blog d'{name}")),
|
page_desc: Some(format!("Blog d'{name}")),
|
||||||
page_kw: Some(
|
page_kw: Some(
|
||||||
vec!["blog", "blogging", "write", "writing"]
|
["blog", "blogging", "write", "writing"]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&tag| tag.to_owned())
|
.map(|&tag| tag.to_owned())
|
||||||
.chain(tags.into_iter().map(|t| t.name))
|
.chain(tags.into_iter().map(|t| t.name))
|
||||||
|
@ -248,7 +263,7 @@ fn get_post(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/blog/rss")]
|
#[get("/blog/rss")]
|
||||||
pub async fn rss(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
async fn rss(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
||||||
HttpResponse::Ok()
|
HttpResponse::Ok()
|
||||||
.append_header(("content-type", MIME_TYPE_RSS))
|
.append_header(("content-type", MIME_TYPE_RSS))
|
||||||
.body(build_rss(
|
.body(build_rss(
|
||||||
|
|
84
src/routes/contact.rs
Normal file
84
src/routes/contact.rs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
use actix_web::{get, routes, web, HttpRequest, HttpResponse, Responder};
|
||||||
|
use cached::proc_macro::once;
|
||||||
|
use ramhorns::Content;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
config::Config,
|
||||||
|
misc::utils::get_url,
|
||||||
|
template::{Infos, NavBar},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[get("/contact")]
|
||||||
|
async fn page(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
||||||
|
HttpResponse::Ok().body(build_page(
|
||||||
|
config.get_ref().to_owned(),
|
||||||
|
get_url(req.connection_info()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[routes]
|
||||||
|
#[get("/contact/{service}")]
|
||||||
|
#[get("/contact/{service}/{scope}")]
|
||||||
|
async fn service_redirection(req: HttpRequest) -> impl Responder {
|
||||||
|
let info = req.match_info();
|
||||||
|
let find_redirection = match info.query("service") {
|
||||||
|
/* Socials links */
|
||||||
|
"twitter" => Some("https://twitter.com/Mylloon".to_owned()),
|
||||||
|
"mastodon" => Some("https://piaille.fr/@mylloon".to_owned()),
|
||||||
|
"discord" => match info.get("scope") {
|
||||||
|
Some("user") => Some("https://discord.com/users/158260864623968257/".to_owned()),
|
||||||
|
Some("guild") => Some("https://discord.gg/Z5ePxH4".to_owned()),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
"reddit" => Some("https://www.reddit.com/user/mylloon".to_owned()),
|
||||||
|
"instagram" => Some("https://www.instagram.com/mylloon/".to_owned()),
|
||||||
|
"kitsu" => Some("https://kitsu.io/users/Mylloon/library?status=completed".to_owned()),
|
||||||
|
"steam" => Some("https://steamcommunity.com/id/mylloon/".to_owned()),
|
||||||
|
"youtube" => Some("https://www.youtube.com/c/Mylloon".to_owned()),
|
||||||
|
"twitch" => Some("https://www.twitch.tv/mylloon".to_owned()),
|
||||||
|
|
||||||
|
/* Forges */
|
||||||
|
"github" => Some("https://github.com/Mylloon".to_owned()),
|
||||||
|
"gitlab" => Some("https://gitlab.com/Mylloon".to_owned()),
|
||||||
|
"codeberg" => Some("https://codeberg.org/Mylloon".to_owned()),
|
||||||
|
"forgejo" => Some("https://git.mylloon.fr/Anri".to_owned()),
|
||||||
|
|
||||||
|
/* Others */
|
||||||
|
"keyoxide" => {
|
||||||
|
Some("https://keyoxide.org/27024A99057E58B8087A5022A82D63DFF8D1317F".to_owned())
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(redirection) = find_redirection {
|
||||||
|
// Redirect to the desired service
|
||||||
|
actix_web::web::Redirect::to(redirection)
|
||||||
|
} else {
|
||||||
|
// By default, returns to the contact page
|
||||||
|
actix_web::web::Redirect::to("/contact")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Content, Debug)]
|
||||||
|
struct NetworksTemplate {
|
||||||
|
navbar: NavBar,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[once(time = 60)]
|
||||||
|
fn build_page(config: Config, url: String) -> String {
|
||||||
|
config.tmpl.render(
|
||||||
|
"contact.html",
|
||||||
|
NetworksTemplate {
|
||||||
|
navbar: NavBar {
|
||||||
|
contact: true,
|
||||||
|
..NavBar::default()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Infos {
|
||||||
|
page_title: Some("Contacts".into()),
|
||||||
|
page_desc: Some(format!("Réseaux d'{}", config.fc.name.unwrap_or_default())),
|
||||||
|
page_kw: None,
|
||||||
|
url,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
|
@ -6,20 +6,21 @@ use crate::{
|
||||||
github::{fetch_pr, ProjectState},
|
github::{fetch_pr, ProjectState},
|
||||||
utils::get_url,
|
utils::get_url,
|
||||||
},
|
},
|
||||||
template::Infos,
|
template::{Infos, NavBar},
|
||||||
};
|
};
|
||||||
use actix_web::{get, web, HttpRequest, HttpResponse, Responder};
|
use actix_web::{get, web, HttpRequest, HttpResponse, Responder};
|
||||||
use cached::proc_macro::once;
|
use cached::proc_macro::once;
|
||||||
use ramhorns::Content;
|
use ramhorns::Content;
|
||||||
|
|
||||||
#[get("/contrib")]
|
#[get("/contrib")]
|
||||||
pub async fn page(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
async fn page(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
||||||
let url = get_url(req.connection_info());
|
let url = get_url(req.connection_info());
|
||||||
HttpResponse::Ok().body(build_page(config.get_ref().to_owned(), url).await)
|
HttpResponse::Ok().body(build_page(config.get_ref().to_owned(), url).await)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Content, Debug)]
|
#[derive(Content, Debug)]
|
||||||
struct PortfolioTemplate {
|
struct PortfolioTemplate {
|
||||||
|
navbar: NavBar,
|
||||||
error: bool,
|
error: bool,
|
||||||
projects: Option<Vec<Project>>,
|
projects: Option<Vec<Project>>,
|
||||||
waiting: Option<Vec<Project>>,
|
waiting: Option<Vec<Project>>,
|
||||||
|
@ -45,7 +46,12 @@ struct Pull {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[once(time = 120)]
|
#[once(time = 120)]
|
||||||
pub async fn build_page(config: Config, url: String) -> String {
|
async fn build_page(config: Config, url: String) -> String {
|
||||||
|
let navbar = NavBar {
|
||||||
|
contrib: true,
|
||||||
|
..NavBar::default()
|
||||||
|
};
|
||||||
|
|
||||||
// Fetch latest data from github
|
// Fetch latest data from github
|
||||||
let data = match fetch_pr().await {
|
let data = match fetch_pr().await {
|
||||||
Ok(projects) => {
|
Ok(projects) => {
|
||||||
|
@ -107,6 +113,7 @@ pub async fn build_page(config: Config, url: String) -> String {
|
||||||
});
|
});
|
||||||
|
|
||||||
PortfolioTemplate {
|
PortfolioTemplate {
|
||||||
|
navbar,
|
||||||
error: false,
|
error: false,
|
||||||
projects: Some(
|
projects: Some(
|
||||||
data.iter()
|
data.iter()
|
||||||
|
@ -132,6 +139,7 @@ pub async fn build_page(config: Config, url: String) -> String {
|
||||||
eprintln!("{}", e);
|
eprintln!("{}", e);
|
||||||
|
|
||||||
PortfolioTemplate {
|
PortfolioTemplate {
|
||||||
|
navbar,
|
||||||
error: true,
|
error: true,
|
||||||
projects: None,
|
projects: None,
|
||||||
waiting: None,
|
waiting: None,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use actix_web::{get, Responder};
|
use actix_web::{get, Responder};
|
||||||
|
|
||||||
#[get("/cours")]
|
#[get("/cours")]
|
||||||
pub async fn page() -> impl Responder {
|
async fn page() -> impl Responder {
|
||||||
// TODO
|
// TODO
|
||||||
actix_web::web::Redirect::to("/")
|
actix_web::web::Redirect::to("/")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use actix_web::{get, Responder};
|
use actix_web::{get, Responder};
|
||||||
|
|
||||||
#[get("/cv")]
|
#[get("/cv")]
|
||||||
pub async fn page() -> impl Responder {
|
async fn page() -> impl Responder {
|
||||||
// TODO
|
// TODO
|
||||||
actix_web::web::Redirect::to("/")
|
actix_web::web::Redirect::to("/")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use actix_web::{get, Responder};
|
use actix_web::{get, Responder};
|
||||||
|
|
||||||
#[get("/gaming")]
|
#[get("/gaming")]
|
||||||
pub async fn page() -> impl Responder {
|
async fn page() -> impl Responder {
|
||||||
// TODO
|
// TODO
|
||||||
actix_web::web::Redirect::to("/")
|
actix_web::web::Redirect::to("/")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,42 @@
|
||||||
use actix_web::{get, web, HttpRequest, HttpResponse, Responder};
|
use actix_web::{get, web, HttpRequest, HttpResponse, Responder};
|
||||||
use cached::proc_macro::once;
|
use cached::proc_macro::once;
|
||||||
|
use ramhorns::Content;
|
||||||
|
|
||||||
use crate::{config::Config, misc::utils::get_url, template::Infos};
|
use crate::{
|
||||||
|
config::Config,
|
||||||
|
misc::utils::get_url,
|
||||||
|
template::{Infos, NavBar},
|
||||||
|
};
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
pub async fn page(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
async fn page(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
||||||
HttpResponse::Ok().body(build_page(
|
HttpResponse::Ok().body(build_page(
|
||||||
config.get_ref().to_owned(),
|
config.get_ref().to_owned(),
|
||||||
get_url(req.connection_info()),
|
get_url(req.connection_info()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Content, Debug)]
|
||||||
|
struct IndexTemplate {
|
||||||
|
navbar: NavBar,
|
||||||
|
fullname: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[once(time = 60)]
|
#[once(time = 60)]
|
||||||
pub fn build_page(config: Config, url: String) -> String {
|
fn build_page(config: Config, url: String) -> String {
|
||||||
config.tmpl.render(
|
config.tmpl.render(
|
||||||
"index.html",
|
"index.html",
|
||||||
(),
|
IndexTemplate {
|
||||||
|
navbar: NavBar {
|
||||||
|
index: true,
|
||||||
|
..NavBar::default()
|
||||||
|
},
|
||||||
|
fullname: config
|
||||||
|
.fc
|
||||||
|
.fullname
|
||||||
|
.to_owned()
|
||||||
|
.unwrap_or("Fullname".to_owned()),
|
||||||
|
},
|
||||||
Infos {
|
Infos {
|
||||||
page_title: config.fc.fullname,
|
page_title: config.fc.fullname,
|
||||||
page_desc: Some("Page principale".into()),
|
page_desc: Some("Page principale".into()),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use actix_web::{get, Responder};
|
use actix_web::{get, Responder};
|
||||||
|
|
||||||
#[get("/memorial")]
|
#[get("/memorial")]
|
||||||
pub async fn page() -> impl Responder {
|
async fn page() -> impl Responder {
|
||||||
// Memorial? J'espere ne jamais faire cette page lol
|
// Memorial? J'espere ne jamais faire cette page lol
|
||||||
actix_web::web::Redirect::to("/")
|
actix_web::web::Redirect::to("/")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
pub mod agreements;
|
pub mod agreements;
|
||||||
pub mod api_v1;
|
pub mod api_v1;
|
||||||
pub mod blog;
|
pub mod blog;
|
||||||
|
pub mod contact;
|
||||||
pub mod contrib;
|
pub mod contrib;
|
||||||
pub mod cours;
|
pub mod cours;
|
||||||
pub mod cv;
|
pub mod cv;
|
||||||
pub mod gaming;
|
pub mod gaming;
|
||||||
pub mod index;
|
pub mod index;
|
||||||
pub mod memorial;
|
pub mod memorial;
|
||||||
pub mod networks;
|
|
||||||
pub mod not_found;
|
pub mod not_found;
|
||||||
pub mod portfolio;
|
pub mod portfolio;
|
||||||
pub mod setup;
|
pub mod setup;
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
use actix_web::{get, web, HttpRequest, HttpResponse, Responder};
|
|
||||||
use cached::proc_macro::once;
|
|
||||||
|
|
||||||
use crate::{config::Config, misc::utils::get_url, template::Infos};
|
|
||||||
|
|
||||||
#[get("/networks")]
|
|
||||||
pub async fn page(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
|
||||||
HttpResponse::Ok().body(build_page(
|
|
||||||
config.get_ref().to_owned(),
|
|
||||||
get_url(req.connection_info()),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[once(time = 60)]
|
|
||||||
pub fn build_page(config: Config, url: String) -> String {
|
|
||||||
config.tmpl.render(
|
|
||||||
"networks.html",
|
|
||||||
(),
|
|
||||||
Infos {
|
|
||||||
page_title: Some("Mes réseaux".into()),
|
|
||||||
page_desc: Some(format!("Réseaux d'{}", config.fc.name.unwrap_or_default())),
|
|
||||||
page_kw: None,
|
|
||||||
url,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,13 +1,39 @@
|
||||||
use actix_web::{web, HttpResponse, Responder};
|
use actix_web::{web, HttpRequest, HttpResponse, Responder};
|
||||||
use cached::proc_macro::once;
|
use cached::proc_macro::once;
|
||||||
|
use ramhorns::Content;
|
||||||
|
|
||||||
use crate::{config::Config, template::Infos};
|
use crate::{
|
||||||
|
config::Config,
|
||||||
|
misc::utils::get_url,
|
||||||
|
template::{Infos, NavBar},
|
||||||
|
};
|
||||||
|
|
||||||
pub async fn page(config: web::Data<Config>) -> impl Responder {
|
pub async fn page(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
||||||
HttpResponse::NotFound().body(build_page(config.get_ref().to_owned()))
|
HttpResponse::NotFound().body(build_page(
|
||||||
|
config.get_ref().to_owned(),
|
||||||
|
get_url(req.connection_info()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Content, Debug)]
|
||||||
|
struct NotFoundTemplate {
|
||||||
|
navbar: NavBar,
|
||||||
|
www: String,
|
||||||
|
onion: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[once(time = 60)]
|
#[once(time = 60)]
|
||||||
pub fn build_page(config: Config) -> String {
|
fn build_page(config: Config, url: String) -> String {
|
||||||
config.tmpl.render("404.html", (), Infos::default())
|
config.tmpl.render(
|
||||||
|
"404.html",
|
||||||
|
NotFoundTemplate {
|
||||||
|
navbar: NavBar::default(),
|
||||||
|
www: url,
|
||||||
|
onion: config.fc.onion,
|
||||||
|
},
|
||||||
|
Infos {
|
||||||
|
page_desc: Some("Une page perdu du web".into()),
|
||||||
|
..Infos::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,11 @@ use crate::{
|
||||||
markdown::{read_file, File},
|
markdown::{read_file, File},
|
||||||
utils::get_url,
|
utils::get_url,
|
||||||
},
|
},
|
||||||
template::Infos,
|
template::{Infos, NavBar},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[get("/portfolio")]
|
#[get("/portfolio")]
|
||||||
pub async fn page(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
async fn page(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
||||||
HttpResponse::Ok().body(build_page(
|
HttpResponse::Ok().body(build_page(
|
||||||
config.get_ref().to_owned(),
|
config.get_ref().to_owned(),
|
||||||
get_url(req.connection_info()),
|
get_url(req.connection_info()),
|
||||||
|
@ -22,62 +22,38 @@ pub async fn page(req: HttpRequest, config: web::Data<Config>) -> impl Responder
|
||||||
|
|
||||||
#[derive(Content, Debug)]
|
#[derive(Content, Debug)]
|
||||||
struct PortfolioTemplate<'a> {
|
struct PortfolioTemplate<'a> {
|
||||||
bots_app: Option<Vec<File>>,
|
navbar: NavBar,
|
||||||
bots_loc: Option<String>,
|
location_apps: Option<&'a str>,
|
||||||
persos_app: Option<Vec<File>>,
|
apps: Option<Vec<File>>,
|
||||||
persos_loc: Option<String>,
|
|
||||||
univ_content: Option<String>,
|
|
||||||
univ_loc: Option<String>,
|
|
||||||
err_msg: &'a str,
|
err_msg: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[once(time = 60)]
|
#[once(time = 60)]
|
||||||
pub fn build_page(config: Config, url: String) -> String {
|
fn build_page(config: Config, url: String) -> String {
|
||||||
let projects_dir = "data/projects";
|
let projects_dir = "data/projects";
|
||||||
let ext = ".md";
|
let ext = ".md";
|
||||||
|
|
||||||
// Get bots apps
|
// Get apps
|
||||||
let bots_apps_loc = format!("{projects_dir}/bots");
|
let apps = glob(&format!("{projects_dir}/*{ext}"))
|
||||||
let bots_apps = glob(&format!("{bots_apps_loc}/*{ext}"))
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map(|e| read_file(&e.unwrap().to_string_lossy()).unwrap())
|
.map(|e| read_file(&e.unwrap().to_string_lossy()).unwrap())
|
||||||
.collect::<Vec<File>>();
|
.collect::<Vec<File>>();
|
||||||
|
|
||||||
// Get perso apps
|
let bots_app = if apps.is_empty() {
|
||||||
let perso_apps_loc = format!("{projects_dir}/perso");
|
(None, Some(projects_dir))
|
||||||
let perso_apps = glob(&format!("{perso_apps_loc}/*{ext}"))
|
|
||||||
.unwrap()
|
|
||||||
.map(|e| read_file(&e.unwrap().to_string_lossy()).unwrap())
|
|
||||||
.collect::<Vec<File>>();
|
|
||||||
|
|
||||||
let univ_loc = format!("{projects_dir}/univ{ext}");
|
|
||||||
|
|
||||||
let (bots_app, bots_loc) = if bots_apps.is_empty() {
|
|
||||||
(None, Some(bots_apps_loc))
|
|
||||||
} else {
|
} else {
|
||||||
(Some(bots_apps), None)
|
(Some(apps), None)
|
||||||
};
|
|
||||||
|
|
||||||
let (persos_app, persos_loc) = if perso_apps.is_empty() {
|
|
||||||
(None, Some(perso_apps_loc))
|
|
||||||
} else {
|
|
||||||
(Some(perso_apps), None)
|
|
||||||
};
|
|
||||||
|
|
||||||
let (univ_content, univ_loc) = match read_file(&univ_loc) {
|
|
||||||
Some(data) => (Some(data.content), None),
|
|
||||||
_ => (None, Some(univ_loc)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config.tmpl.render(
|
config.tmpl.render(
|
||||||
"portfolio.html",
|
"portfolio.html",
|
||||||
PortfolioTemplate {
|
PortfolioTemplate {
|
||||||
bots_app,
|
navbar: NavBar {
|
||||||
bots_loc,
|
portfolio: true,
|
||||||
persos_app,
|
..NavBar::default()
|
||||||
persos_loc,
|
},
|
||||||
univ_content,
|
apps: bots_app.0,
|
||||||
univ_loc,
|
location_apps: bots_app.1,
|
||||||
err_msg: "is empty",
|
err_msg: "is empty",
|
||||||
},
|
},
|
||||||
Infos {
|
Infos {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use actix_web::{get, Responder};
|
use actix_web::{get, Responder};
|
||||||
|
|
||||||
#[get("/setup")]
|
#[get("/setup")]
|
||||||
pub async fn page() -> impl Responder {
|
async fn page() -> impl Responder {
|
||||||
// Explication de l'histoire de par exemple wiki/cat et le follow up
|
// Explication de l'histoire de par exemple wiki/cat et le follow up
|
||||||
// avec les futures video youtube probablement un shortcut
|
// avec les futures video youtube probablement un shortcut
|
||||||
// vers un billet de blog
|
// vers un billet de blog
|
||||||
|
|
|
@ -4,7 +4,7 @@ use cached::proc_macro::once;
|
||||||
use crate::{config::Config, misc::utils::get_url, template::Infos};
|
use crate::{config::Config, misc::utils::get_url, template::Infos};
|
||||||
|
|
||||||
#[get("/web3")]
|
#[get("/web3")]
|
||||||
pub async fn page(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
async fn page(req: HttpRequest, config: web::Data<Config>) -> impl Responder {
|
||||||
HttpResponse::Ok().body(build_page(
|
HttpResponse::Ok().body(build_page(
|
||||||
config.get_ref().to_owned(),
|
config.get_ref().to_owned(),
|
||||||
get_url(req.connection_info()),
|
get_url(req.connection_info()),
|
||||||
|
@ -12,7 +12,7 @@ pub async fn page(req: HttpRequest, config: web::Data<Config>) -> impl Responder
|
||||||
}
|
}
|
||||||
|
|
||||||
#[once(time = 60)]
|
#[once(time = 60)]
|
||||||
pub fn build_page(config: Config, url: String) -> String {
|
fn build_page(config: Config, url: String) -> String {
|
||||||
config.tmpl.render(
|
config.tmpl.render(
|
||||||
"web3.html",
|
"web3.html",
|
||||||
(),
|
(),
|
||||||
|
|
|
@ -22,6 +22,16 @@ pub struct Infos {
|
||||||
pub url: String,
|
pub url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Content, Debug, Default)]
|
||||||
|
pub struct NavBar {
|
||||||
|
pub index: bool,
|
||||||
|
pub blog: bool,
|
||||||
|
pub portfolio: bool,
|
||||||
|
pub contact: bool,
|
||||||
|
pub contrib: bool,
|
||||||
|
pub cours: bool,
|
||||||
|
}
|
||||||
|
|
||||||
/// Final structure given to template
|
/// Final structure given to template
|
||||||
#[derive(Content, Debug)]
|
#[derive(Content, Debug)]
|
||||||
struct Data<T> {
|
struct Data<T> {
|
||||||
|
|
BIN
static/badges/friends/21_12.webp
Normal file
BIN
static/badges/friends/21_12.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
BIN
static/badges/friends/azazouille.webp
Normal file
BIN
static/badges/friends/azazouille.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
|
@ -1,127 +1,54 @@
|
||||||
@media (prefers-color-scheme: light) {
|
@media (prefers-color-scheme: light) {
|
||||||
:root {
|
:root {
|
||||||
--selection: #36837db3;
|
|
||||||
--bg: #ffffff;
|
|
||||||
--line: #aebed0;
|
--line: #aebed0;
|
||||||
--date: #d2e0f0;
|
--date: #d2e0f0;
|
||||||
--point: #8c9daf;
|
--point: #8c9daf;
|
||||||
--bg-hover: #cedce2;
|
--bg-hover: #cedce2;
|
||||||
--point-hover: #ff00ff;
|
--point-hover: #ff00ff;
|
||||||
--font-color: #18181b;
|
|
||||||
--title-color: #a14cb3;
|
--title-color: #a14cb3;
|
||||||
|
--rss-inverse: 0%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
:root {
|
:root {
|
||||||
--selection: #4bad9480;
|
|
||||||
--bg: #171e26;
|
|
||||||
--line: #374351;
|
--line: #374351;
|
||||||
--date: #242e38;
|
--date: #242e38;
|
||||||
--point: #515f70;
|
--point: #515f70;
|
||||||
--bg-hover: #1f2730;
|
--bg-hover: #1f2730;
|
||||||
--point-hover: #ff00ff;
|
--point-hover: #ff00ff;
|
||||||
--font-color: #a1a1aa;
|
|
||||||
--title-color: #a25add;
|
--title-color: #a25add;
|
||||||
|
--rss-inverse: 80%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
/* Title */
|
||||||
--font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
::selection {
|
|
||||||
color: rgb(255, 255, 255);
|
|
||||||
background: var(--selection);
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
background-color: var(--bg);
|
|
||||||
font-family: "Segoe UI", Arial, sans-serif, "Segoe UI Emoji",
|
|
||||||
"Segoe UI Symbol";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scrollbar - Firefox */
|
|
||||||
* {
|
|
||||||
scrollbar-color: var(--font-color) var(--bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scrollbar - Chrome */
|
|
||||||
*::-webkit-scrollbar {
|
|
||||||
width: 7px;
|
|
||||||
height: 9px;
|
|
||||||
background: var(--bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
*::-webkit-scrollbar-thumb {
|
|
||||||
background-color: var(--font-color);
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Title of page */
|
|
||||||
h1 {
|
h1 {
|
||||||
color: var(--font-color);
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.3cap;
|
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2,
|
/* RSS link */
|
||||||
p {
|
#rss::before {
|
||||||
margin: 0px;
|
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='20' width='20' viewBox='0 0 24 24' %3E%3Cpath d='M6.18 15.64a2.18 2.18 0 0 1 2.18 2.18C8.36 19 7.38 20 6.18 20 5 20 4 19 4 17.82a2.18 2.18 0 0 1 2.18-2.18M4 4.44A15.56 15.56 0 0 1 19.56 20h-2.83A12.73 12.73 0 0 0 4 7.27V4.44m0 5.66a9.9 9.9 0 0 1 9.9 9.9h-2.83A7.07 7.07 0 0 0 4 12.93V10.1Z' %3E%3C/path%3E%3C/svg%3E");
|
||||||
}
|
padding-right: 2px;
|
||||||
|
vertical-align: middle;
|
||||||
h1,
|
filter: invert(var(--rss-inverse));
|
||||||
footer {
|
|
||||||
text-align: center;
|
|
||||||
font-size: calc(var(--font-size) * 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
footer > * {
|
|
||||||
color: var(--font-color);
|
|
||||||
font-weight: bold;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: calc(var(--font-size) / 1.5);
|
|
||||||
text-transform: uppercase;
|
|
||||||
opacity: 0.7;
|
|
||||||
letter-spacing: 0.15rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer > *::before {
|
|
||||||
content: "> ";
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
color: var(--title-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeline {
|
|
||||||
box-sizing: border-box;
|
|
||||||
color: var(--font-color);
|
|
||||||
padding: 30px 20px;
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Barre */
|
|
||||||
.timeline > ul {
|
|
||||||
list-style-type: none;
|
|
||||||
border-left: 2px solid var(--line);
|
|
||||||
padding: 0px 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Card */
|
/* Card */
|
||||||
.timeline > ul > li {
|
main li {
|
||||||
padding: 20px 20px;
|
padding: 20px 20px;
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dates */
|
main li:hover {
|
||||||
.timeline > ul > li > span {
|
background: var(--bg-hover);
|
||||||
display: inline-block;
|
}
|
||||||
|
|
||||||
|
/* Card dates */
|
||||||
|
main span {
|
||||||
background-color: var(--date);
|
background-color: var(--date);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 2px 5px;
|
padding: 2px 5px;
|
||||||
|
@ -129,82 +56,48 @@ a:hover {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Titles */
|
/* Card text */
|
||||||
.timeline > ul > li > .content > h2 {
|
li h2,
|
||||||
|
li p {
|
||||||
|
margin: 0px;
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Card titles */
|
||||||
|
li h2 {
|
||||||
color: var(--title-color);
|
color: var(--title-color);
|
||||||
font-size: var(--font-size);
|
font-size: var(--font-size);
|
||||||
padding-top: 5px;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Descriptions */
|
/* Card descriptions */
|
||||||
.timeline > ul > li > .content > p {
|
li p {
|
||||||
padding-top: 5px;
|
|
||||||
font-size: calc(var(--font-size) - 2px);
|
font-size: calc(var(--font-size) - 2px);
|
||||||
max-width: 25em;
|
|
||||||
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Points côté */
|
/* Timeline bar */
|
||||||
.timeline > ul > li::before {
|
main ul {
|
||||||
|
list-style-type: none;
|
||||||
|
border-left: 2px solid var(--line);
|
||||||
|
padding: 0px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Timeline dot */
|
||||||
|
main li::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
||||||
content: "";
|
content: "";
|
||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
background-color: var(--point);
|
background-color: var(--point);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
||||||
left: -11px;
|
left: -11px;
|
||||||
top: 59px;
|
top: 59px;
|
||||||
|
|
||||||
transition: 0.2s;
|
transition: 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Card hover */
|
main li:hover::before {
|
||||||
.timeline > ul > li:hover {
|
|
||||||
background-color: var(--bg-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Point côté hover */
|
|
||||||
.timeline > ul > li:hover::before {
|
|
||||||
background-color: var(--point-hover);
|
background-color: var(--point-hover);
|
||||||
box-shadow: 0px 0px 10px 2px var(--point-hover);
|
box-shadow: 0px 0px 10px 2px var(--point-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
nav {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#rss {
|
|
||||||
text-transform: lowercase;
|
|
||||||
color: var(--font-color);
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
border: 0;
|
|
||||||
margin: 0;
|
|
||||||
height: 1px;
|
|
||||||
background: var(--line);
|
|
||||||
margin: 2rem auto;
|
|
||||||
width: 20%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#rss:hover {
|
|
||||||
color: var(--title-color);
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 300px) {
|
|
||||||
.timeline {
|
|
||||||
padding: 30px 5px 30px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeline > ul > li > .content > h2 > a {
|
|
||||||
color: var(--title-color);
|
|
||||||
font-size: calc(var(--font-size) - 2px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
@media (prefers-color-scheme: light) {
|
@media (prefers-color-scheme: light) {
|
||||||
:root {
|
:root {
|
||||||
--selection: rgba(92, 54, 131, 0.7);
|
|
||||||
--bg: #ffffff;
|
|
||||||
--font-color: #18181b;
|
|
||||||
--code-font-color: #333333;
|
--code-font-color: #333333;
|
||||||
--code-bg-color: #eeeeee;
|
--code-bg-color: #eeeeee;
|
||||||
--quote-border-color: #9852fa;
|
--quote-border-color: #9852fa;
|
||||||
--quote-bg-color: #d8d6d6;
|
--quote-bg-color: #d8d6d6;
|
||||||
--link-hover-color: #fd62af;
|
|
||||||
--separator-color: #cccccc;
|
--separator-color: #cccccc;
|
||||||
--tag-bg-color: #d2e0f0;
|
--tag-bg-color: #d2e0f0;
|
||||||
}
|
}
|
||||||
|
@ -15,103 +11,68 @@
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
:root {
|
:root {
|
||||||
--selection: rgba(124, 75, 173, 0.5);
|
|
||||||
--bg: #171e26;
|
|
||||||
--font-color: #bcbcc5;
|
|
||||||
--code-font-color: #eeeeee;
|
--code-font-color: #eeeeee;
|
||||||
--code-bg-color: #333333;
|
--code-bg-color: #333333;
|
||||||
--quote-border-color: #bd93f9;
|
--quote-border-color: #bd93f9;
|
||||||
--quote-bg-color: #273341;
|
--quote-bg-color: #273341;
|
||||||
--link-hover-color: #ff80bf;
|
|
||||||
--separator-color: #414558;
|
--separator-color: #414558;
|
||||||
--tag-bg-color: #242e38;
|
--tag-bg-color: #242e38;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--font-size: 17px;
|
|
||||||
--max-width: 750px;
|
--max-width: 750px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Page */
|
||||||
html {
|
html {
|
||||||
font-family: "Segoe UI", Arial, sans-serif, "Segoe UI Emoji",
|
|
||||||
"Segoe UI Symbol";
|
|
||||||
font-size: var(--font-size);
|
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
background-color: var(--bg);
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scrollbar - Firefox */
|
body {
|
||||||
* {
|
max-width: var(--max-width);
|
||||||
scrollbar-color: var(--font-color) var(--bg);
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scrollbar - Chrome */
|
/* Post title */
|
||||||
*::-webkit-scrollbar {
|
header h1 {
|
||||||
width: 7px;
|
font-size: calc(var(--font-size) * 2);
|
||||||
height: 9px;
|
|
||||||
background: var(--bg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar-thumb {
|
/* Post date */
|
||||||
background-color: var(--font-color);
|
header span {
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Post's title */
|
|
||||||
header > h1 {
|
|
||||||
font-size: 2.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Date's title */
|
|
||||||
header > span {
|
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tags */
|
/* Post tags */
|
||||||
header > ul {
|
header > ul:last-of-type {
|
||||||
display: inline;
|
display: inline;
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
header li::before {
|
header > ul:last-of-type li::before {
|
||||||
content: "#";
|
content: "#";
|
||||||
}
|
}
|
||||||
|
|
||||||
header li {
|
header > ul:last-of-type li {
|
||||||
display: inline;
|
display: inline;
|
||||||
background-color: var(--tag-bg-color);
|
background: var(--tag-bg-color);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 2px 8px;
|
padding: 2px 8px;
|
||||||
font-size: calc(var(--font-size) / 1.1);
|
font-size: calc(var(--font-size) * 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection {
|
/* Post */
|
||||||
color: rgb(255, 255, 255);
|
main {
|
||||||
background: var(--selection);
|
margin: 0;
|
||||||
}
|
padding: 0;
|
||||||
|
max-width: 100%;
|
||||||
* {
|
|
||||||
color: var(--font-color);
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
color: var(--font-color);
|
|
||||||
font-size: var(--font-size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Anchors */
|
/* Anchors */
|
||||||
h1:hover > a.anchor::before,
|
:is(h1, h2, h3, h4, h5, h6):hover a.anchor::before {
|
||||||
h2:hover > a.anchor::before,
|
|
||||||
h3:hover > a.anchor::before,
|
|
||||||
h4:hover > a.anchor::before,
|
|
||||||
h5:hover > a.anchor::before,
|
|
||||||
h6:hover > a.anchor::before {
|
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
color: var(--font-color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a.anchor::before {
|
a.anchor::before {
|
||||||
|
@ -122,30 +83,15 @@ a.anchor::before {
|
||||||
|
|
||||||
a.anchor {
|
a.anchor {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
vertical-align: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
/* Links in headers */
|
||||||
margin: 0 auto;
|
:is(h1, h2, h3, h4, h5, h6) a {
|
||||||
max-width: var(--max-width);
|
font-size: inherit;
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer > * {
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-size: calc(var(--font-size) / 1.2);
|
|
||||||
letter-spacing: 0.15rem;
|
|
||||||
opacity: 0.6;
|
|
||||||
text-decoration: none;
|
|
||||||
padding-bottom: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
color: var(--link-hover-color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Separators */
|
||||||
hr {
|
hr {
|
||||||
border: 0;
|
border: 0;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
|
@ -158,7 +104,7 @@ blockquote {
|
||||||
padding: 0.1em 10px;
|
padding: 0.1em 10px;
|
||||||
border-left: 6px solid;
|
border-left: 6px solid;
|
||||||
border-color: var(--quote-border-color);
|
border-color: var(--quote-border-color);
|
||||||
background-color: var(--quote-bg-color);
|
background: var(--quote-bg-color);
|
||||||
border-top-right-radius: 5px;
|
border-top-right-radius: 5px;
|
||||||
border-bottom-right-radius: 5px;
|
border-bottom-right-radius: 5px;
|
||||||
}
|
}
|
||||||
|
@ -173,17 +119,17 @@ img {
|
||||||
/* Code */
|
/* Code */
|
||||||
kbd,
|
kbd,
|
||||||
code {
|
code {
|
||||||
font-family: Consolas, monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Little snippet of code (not blocks) */
|
/* Little snippet of code (not blocks) */
|
||||||
kbd,
|
kbd,
|
||||||
code:not(.hljs):not(:has(svg)) {
|
code:not(.hljs):not(:has(svg)) {
|
||||||
background-color: var(--code-bg-color);
|
background: var(--code-bg-color);
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
color: var(--code-font-color);
|
color: var(--code-font-color);
|
||||||
box-shadow: 0 1px 1px black;
|
box-shadow: 0 1px 1px black;
|
||||||
font-size: calc(var(--font-size) / 1.2);
|
font-size: calc(var(--font-size) * 0.8);
|
||||||
padding: 2px 4px;
|
padding: 2px 4px;
|
||||||
vertical-align: 1.5px;
|
vertical-align: 1.5px;
|
||||||
}
|
}
|
||||||
|
@ -193,6 +139,17 @@ code:not(.hljs):not(:has(svg)) {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hljs::-webkit-scrollbar {
|
||||||
|
width: 7px;
|
||||||
|
height: 9px;
|
||||||
|
background: var(--background);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs::-webkit-scrollbar-thumb {
|
||||||
|
background-color: var(--font-color);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Marge for numbers */
|
/* Marge for numbers */
|
||||||
.hljs-ln-n {
|
.hljs-ln-n {
|
||||||
margin-right: 0.4em;
|
margin-right: 0.4em;
|
||||||
|
@ -201,6 +158,7 @@ code:not(.hljs):not(:has(svg)) {
|
||||||
/* Numbers in codeblocks */
|
/* Numbers in codeblocks */
|
||||||
.hljs-ln-numbers {
|
.hljs-ln-numbers {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
color: var(--font-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix scroll in codeblocks with line numbering */
|
/* Fix scroll in codeblocks with line numbering */
|
||||||
|
@ -210,7 +168,7 @@ table.hljs-ln {
|
||||||
|
|
||||||
/* Background for copy code button */
|
/* Background for copy code button */
|
||||||
.hljs-copy-button {
|
.hljs-copy-button {
|
||||||
background-color: var(--bg) !important;
|
background-color: var(--background) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Light theme for the copy code button */
|
/* Light theme for the copy code button */
|
||||||
|
@ -234,28 +192,23 @@ table.hljs-ln {
|
||||||
visibility: collapse;
|
visibility: collapse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reference to footnotes */
|
||||||
|
.footnote-ref a {
|
||||||
|
text-decoration: underline dotted;
|
||||||
|
font-size: calc(var(--font-size) * 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
/* Footnotes */
|
/* Footnotes */
|
||||||
.footnotes a {
|
.footnotes a {
|
||||||
font-family: "Segoe UI";
|
font-family: "Segoe UI";
|
||||||
text-decoration: underline dotted;
|
text-decoration: underline dotted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reference to footnotes */
|
|
||||||
.footnote-ref > a {
|
|
||||||
text-decoration: underline dotted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mermaid diagrams */
|
/* Mermaid diagrams */
|
||||||
pre:has(code.language-mermaid) {
|
pre:has(code.language-mermaid) {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 750px) {
|
|
||||||
body {
|
|
||||||
margin: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Table of content */
|
/* Table of content */
|
||||||
nav#toc {
|
nav#toc {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -264,6 +217,7 @@ nav#toc {
|
||||||
margin-left: 50px;
|
margin-left: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* breakpoint */
|
||||||
@media only screen and (max-width: 1500px) {
|
@media only screen and (max-width: 1500px) {
|
||||||
/* Visible only on large screens */
|
/* Visible only on large screens */
|
||||||
nav#toc {
|
nav#toc {
|
||||||
|
|
23
static/css/constants.css
Normal file
23
static/css/constants.css
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/* Parameters light */
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
:root {
|
||||||
|
--background: #f1f1f1;
|
||||||
|
--font-color: #18181b;
|
||||||
|
--link-color: #df5a9c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parameters dark */
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--background: #171e26;
|
||||||
|
--font-color: #bcbcc5;
|
||||||
|
--link-color: #ff80bf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Global parameters */
|
||||||
|
:root {
|
||||||
|
--font-size: 1.15rem;
|
||||||
|
--font-family: "Segoe UI", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
|
}
|
53
static/css/contact.css
Normal file
53
static/css/contact.css
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/* https://stackoverflow.com/a/40244401/15436737 */
|
||||||
|
|
||||||
|
/* Title */
|
||||||
|
h1 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 + p {
|
||||||
|
margin: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List */
|
||||||
|
main ul {
|
||||||
|
column-count: 2;
|
||||||
|
column-gap: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
main li > p {
|
||||||
|
margin: 0;
|
||||||
|
padding: 3%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* breakpoint */
|
||||||
|
@media only screen and (max-width: 640px) {
|
||||||
|
main ul {
|
||||||
|
column-count: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Links */
|
||||||
|
main a {
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
color: color-mix(in srgb, var(--font-color) 30%, var(--link-color));
|
||||||
|
}
|
||||||
|
|
||||||
|
main a:after {
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
border-bottom: solid 3px;
|
||||||
|
transform: scaleX(0);
|
||||||
|
transition: transform 250ms ease-in-out;
|
||||||
|
transform-origin: 100% 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
main a:hover:after {
|
||||||
|
transform: scaleX(1);
|
||||||
|
transform-origin: 0 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
main a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
35
static/css/contrib.css
Normal file
35
static/css/contrib.css
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
h2 {
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Element of lists */
|
||||||
|
main li {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
main h1,
|
||||||
|
h2 {
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Links */
|
||||||
|
main a {
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
main a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
main p::after {
|
||||||
|
content: ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
main li:last-child p::after {
|
||||||
|
content: "";
|
||||||
|
}
|
69
static/css/index.css
Normal file
69
static/css/index.css
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
:root {
|
||||||
|
--name-color: #d30f39;
|
||||||
|
--pronouns-color: #6c6f85;
|
||||||
|
--font-color: #4c4f69;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--name-color: #f38ba8;
|
||||||
|
--pronouns-color: #a6adc8;
|
||||||
|
--font-color: #c8d0ee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--title-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Name header */
|
||||||
|
#name {
|
||||||
|
font-size: calc(var(--font-size) * 2.5);
|
||||||
|
font-weight: var(--title-weight);
|
||||||
|
color: var(--name-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#subname {
|
||||||
|
margin-top: 0;
|
||||||
|
font-size: calc(var(--font-size) * 1.07);
|
||||||
|
margin-bottom: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pronouns {
|
||||||
|
font-size: calc(var(--font-size) * 0.8);
|
||||||
|
color: var(--pronouns-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#avatar {
|
||||||
|
width: calc(var(--font-size) * 5);
|
||||||
|
border-radius: 50%;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* breakpoint */
|
||||||
|
@media only screen and (max-width: 640px) {
|
||||||
|
#avatar {
|
||||||
|
position: absolute;
|
||||||
|
width: calc(var(--font-size) * 4);
|
||||||
|
left: 10px;
|
||||||
|
top: -30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Description */
|
||||||
|
h1 {
|
||||||
|
font-weight: var(--title-weight);
|
||||||
|
font-size: calc(var(--font-size) * 1.6);
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Friends */
|
||||||
|
#friends a:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#friends a {
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
71
static/css/languages.css
Normal file
71
static/css/languages.css
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
:root {
|
||||||
|
--lang-size-dot: 0.8em;
|
||||||
|
--lang-margin-text: 3px;
|
||||||
|
--lang-font-size: calc(var(--font-size) * 0.65);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dot */
|
||||||
|
p[data-lang]::before {
|
||||||
|
content: "";
|
||||||
|
|
||||||
|
height: var(--lang-size-dot);
|
||||||
|
width: var(--lang-size-dot);
|
||||||
|
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text */
|
||||||
|
p[data-lang]::after {
|
||||||
|
margin-left: var(--lang-margin-text);
|
||||||
|
font-size: var(--lang-font-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Definitions */
|
||||||
|
p[data-lang="ts"]::before {
|
||||||
|
background-color: #3178c6;
|
||||||
|
}
|
||||||
|
|
||||||
|
p[data-lang="ts"]::after {
|
||||||
|
content: "TypeScript";
|
||||||
|
}
|
||||||
|
|
||||||
|
p[data-lang="rust"]::before {
|
||||||
|
background-color: #dea584;
|
||||||
|
}
|
||||||
|
|
||||||
|
p[data-lang="rust"]::after {
|
||||||
|
content: "Rust";
|
||||||
|
}
|
||||||
|
|
||||||
|
p[data-lang="py"]::before {
|
||||||
|
background-color: #3572a5;
|
||||||
|
}
|
||||||
|
|
||||||
|
p[data-lang="py"]::after {
|
||||||
|
content: "Python";
|
||||||
|
}
|
||||||
|
|
||||||
|
p[data-lang="ocaml"]::before {
|
||||||
|
background-color: #ef7a08;
|
||||||
|
}
|
||||||
|
|
||||||
|
p[data-lang="ocaml"]::after {
|
||||||
|
content: "OCaml";
|
||||||
|
}
|
||||||
|
|
||||||
|
p[data-lang="js"]::before {
|
||||||
|
background-color: #e3d357;
|
||||||
|
}
|
||||||
|
|
||||||
|
p[data-lang="js"]::after {
|
||||||
|
content: "JavaScript";
|
||||||
|
}
|
||||||
|
|
||||||
|
p[data-lang="c"]::before {
|
||||||
|
background-color: #555555;
|
||||||
|
}
|
||||||
|
|
||||||
|
p[data-lang="c"]::after {
|
||||||
|
content: "C";
|
||||||
|
}
|
86
static/css/portfolio.css
Normal file
86
static/css/portfolio.css
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
:root {
|
||||||
|
--extreme: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--extreme: black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--border-color: #6e6e6f;
|
||||||
|
--font-size-card: calc(var(--font-size) * 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
max-width: 840px; /* breakpoint */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List */
|
||||||
|
main ul {
|
||||||
|
padding: 0;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* breakpoint */
|
||||||
|
@media only screen and (max-width: 740px) {
|
||||||
|
main ul {
|
||||||
|
grid-template-columns: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Card */
|
||||||
|
main li {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
|
||||||
|
|
||||||
|
background: color-mix(in srgb, var(--background) 90%, var(--extreme));
|
||||||
|
border: 1px solid
|
||||||
|
color-mix(in srgb, var(--background) 50%, var(--border-color));
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
padding: 10px;
|
||||||
|
margin-block: 10px;
|
||||||
|
margin-inline: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main li:hover {
|
||||||
|
background: color-mix(in srgb, var(--background) 40%, var(--extreme));
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Element */
|
||||||
|
div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Element title */
|
||||||
|
div h3 {
|
||||||
|
margin-block: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Element description */
|
||||||
|
span {
|
||||||
|
margin: auto;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Element text */
|
||||||
|
div p,
|
||||||
|
div a {
|
||||||
|
font-size: var(--font-size-card);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Element language */
|
||||||
|
p[data-lang] {
|
||||||
|
margin: 0;
|
||||||
|
}
|
|
@ -1,189 +1,67 @@
|
||||||
/* Normal font */
|
/* Theme of the pages */
|
||||||
@font-face {
|
|
||||||
font-family: "Luciole";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: normal;
|
|
||||||
src: url(/css/fonts/Luciole-Regular.ttf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Italic font */
|
|
||||||
@font-face {
|
|
||||||
font-family: "Luciole";
|
|
||||||
font-style: italic;
|
|
||||||
font-weight: normal;
|
|
||||||
src: url(/css/fonts/Luciole-Regular-Italic.ttf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bold fond */
|
|
||||||
@font-face {
|
|
||||||
font-family: "Luciole";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: bold;
|
|
||||||
src: url(/css/fonts/Luciole-Bold.ttf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bold italic font */
|
|
||||||
@font-face {
|
|
||||||
font-family: "Luciole";
|
|
||||||
font-style: italic;
|
|
||||||
font-weight: bold;
|
|
||||||
src: url(/css/fonts/Luciole-Bold-Italic.ttf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Page bottom */
|
|
||||||
footer {
|
|
||||||
margin-top: 1em;
|
|
||||||
height: 3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Regular tags */
|
|
||||||
html {
|
html {
|
||||||
position: relative;
|
background-color: var(--background);
|
||||||
min-height: 100vh;
|
font-family: "Segoe UI", "Segoe UI Emoji", "Segoe UI Symbol", system-ui;
|
||||||
height: 100%;
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body,
|
||||||
position: relative;
|
|
||||||
padding-bottom: 3em;
|
|
||||||
min-height: 90%;
|
|
||||||
background-color: rgb(24, 24, 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
p,
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
li,
|
|
||||||
a {
|
a {
|
||||||
font-family: "Luciole", sans-serif;
|
color: var(--font-color);
|
||||||
|
font-size: var(--font-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection {
|
a {
|
||||||
color: rgb(255, 255, 255);
|
transition: opacity 0.2s;
|
||||||
background: rgba(124, 75, 173, 0.486);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Frames */
|
a:hover {
|
||||||
h1.subtitle {
|
opacity: 0.6;
|
||||||
text-decoration: none;
|
|
||||||
color: rgb(28, 118, 236);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h1#title {
|
main {
|
||||||
text-align: center;
|
|
||||||
color: rgb(28, 236, 174);
|
|
||||||
}
|
|
||||||
|
|
||||||
h2.subtitle,
|
|
||||||
h2.subtitle a {
|
|
||||||
color: rgb(28, 118, 236) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3.subsubtitle,
|
|
||||||
#content h3.subsubtitle a {
|
|
||||||
text-align: left;
|
|
||||||
color: rgb(149, 87, 201);
|
|
||||||
}
|
|
||||||
|
|
||||||
#content h3.subsubtitle a:hover {
|
|
||||||
color: rgb(0, 181, 236);
|
|
||||||
transition: color 0.1s;
|
|
||||||
}
|
|
||||||
|
|
||||||
div#content {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
margin-top: 2%;
|
|
||||||
padding: 0.9% 0.9% 0.9% 0.9%;
|
|
||||||
width: 42%;
|
|
||||||
border-radius: 6px;
|
|
||||||
border: 1px solid rgb(170, 170, 170);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 850px) {
|
|
||||||
/* Mobile display */
|
|
||||||
div#content {
|
|
||||||
width: 90%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#content a,
|
|
||||||
#content a:visited,
|
|
||||||
#content ul {
|
|
||||||
text-decoration: none;
|
|
||||||
color: rgb(201, 201, 201);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#content p {
|
|
||||||
text-decoration: none;
|
|
||||||
color: rgb(201, 201, 201);
|
|
||||||
text-align: center;
|
|
||||||
padding: 0.7em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#content a:hover {
|
|
||||||
color: rgb(0, 181, 236);
|
|
||||||
transition: color 0.1s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* https://stackoverflow.com/a/40244401/15436737 */
|
|
||||||
|
|
||||||
#content a {
|
|
||||||
position: relative;
|
position: relative;
|
||||||
text-decoration: none;
|
font-size: var(--font-size);
|
||||||
|
padding: 2em 1em;
|
||||||
|
font-family: var(--font-family);
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 640px; /* breakpoint */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Navigation bar across all of the pages */
|
||||||
|
header nav {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header nav li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content a:after {
|
/* Maybe do this only with 'large' screens */
|
||||||
display: block;
|
header nav p::after {
|
||||||
|
content: "·";
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* breakpoint */
|
||||||
|
@media only screen and (max-width: 640px) {
|
||||||
|
header nav p::after {
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header nav li:last-child p::after {
|
||||||
content: "";
|
content: "";
|
||||||
border-bottom: solid 3px;
|
|
||||||
transform: scaleX(0);
|
|
||||||
transition: transform 250ms ease-in-out;
|
|
||||||
transform-origin: 100% 50%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#content a:hover:after {
|
header nav a {
|
||||||
transform: scaleX(1);
|
|
||||||
transform-origin: 0 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------- */
|
|
||||||
|
|
||||||
div.subcontent {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
margin-top: 5%;
|
|
||||||
padding: 1.2% 1.2% 1.2% 1.2%;
|
|
||||||
width: 78%;
|
|
||||||
border-radius: 6px;
|
|
||||||
border: 1px solid rgb(170, 170, 170);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#listecontent li {
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Back links going to the index */
|
|
||||||
footer.backToIndexPage {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer.backToIndexPage a {
|
|
||||||
color: rgb(114, 180, 76);
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
color: var(--link-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
footer.backToIndexPage a:hover {
|
header nav a:hover {
|
||||||
color: rgb(152, 187, 132);
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hide content */
|
.bold {
|
||||||
.hide {
|
font-weight: bold;
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
|
|
32
static/js/index.js
Normal file
32
static/js/index.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
class Tag {
|
||||||
|
constructor(variant, style = "") {
|
||||||
|
this.variant = variant;
|
||||||
|
this.style = style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("load", () => {
|
||||||
|
const tags = [
|
||||||
|
new Tag("Comment ça marche un PC 😵💫"),
|
||||||
|
new Tag("Idiot certifié"),
|
||||||
|
new Tag("undefined", "font-family: monospace"),
|
||||||
|
new Tag("/api/v1/love", "font-family: monospace"),
|
||||||
|
new Tag("Étudiant qui va rater son master"),
|
||||||
|
new Tag("Peak D2 sur Valo 🤡"),
|
||||||
|
new Tag(
|
||||||
|
"1312",
|
||||||
|
`
|
||||||
|
display: inline-block;
|
||||||
|
background: linear-gradient(to bottom right, red 0%, red 50%, black 50%);
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
`
|
||||||
|
),
|
||||||
|
new Tag("Nul en CSS", "font-family: 'Comic Sans MS', cursive"),
|
||||||
|
];
|
||||||
|
|
||||||
|
const random = Math.round(Math.random() * (tags.length - 1));
|
||||||
|
const element = document.getElementById("subname");
|
||||||
|
element.textContent = tags[random].variant;
|
||||||
|
element.style = tags[random].style;
|
||||||
|
});
|
|
@ -1,10 +1,37 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html class="index" lang="fr">
|
<html lang="fr">
|
||||||
<head dir="ltr">
|
<head dir="ltr">
|
||||||
{{>head.html}}
|
{{>head.html}}
|
||||||
</head>
|
</head>
|
||||||
<body class="index">
|
<body>
|
||||||
<p style="color: aliceblue">404 :/</p>
|
<header>{{>navbar.html}}</header>
|
||||||
{{>footer.html}}
|
<main>
|
||||||
|
{{#data}}
|
||||||
|
|
||||||
|
<h1>Perdu ?</h1>
|
||||||
|
|
||||||
|
<p>Vous pouvez revenir sur le site via :</p>
|
||||||
|
<ul>
|
||||||
|
<li><p>La barre de navigation</p></li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Le <a href="{{www}} ">site internet</a> (disponible grâce au projet
|
||||||
|
<a href="http://info.cern.ch/hypertext/WWW/TheProject.html">W3</a>).
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
{{#onion}}
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Le <a href="{{onion}} ">site onion</a> (disponible grâce au réseau
|
||||||
|
<a href="https://www.torproject.org/">Tor</a>).
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
{{/onion}}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{{/data}}
|
||||||
|
</main>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
<footer>
|
|
||||||
<a href="/blog">> Retour à la liste des posts</a>
|
|
||||||
</footer>
|
|
|
@ -1,8 +0,0 @@
|
||||||
<title>{{page_title}}{{#page_title}} - {{/page_title}}{{app_name}}</title>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<link rel="author" href="/humans.txt" />
|
|
||||||
<link rel="alternate" type="application/rss+xml" title="RSS" href="/blog/rss" />
|
|
||||||
|
|
||||||
{{>icons.html}} {{>metadata.html}}
|
|
|
@ -1,34 +1,40 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html class="index" lang="fr">
|
<html lang="fr">
|
||||||
<head dir="ltr">
|
<head dir="ltr">
|
||||||
{{>blog/head.html}}
|
{{>head.html}}
|
||||||
|
<link
|
||||||
|
rel="alternate"
|
||||||
|
type="application/rss+xml"
|
||||||
|
title="RSS"
|
||||||
|
href="/blog/rss"
|
||||||
|
/>
|
||||||
<link rel="stylesheet" href="/css/blog/index.css" />
|
<link rel="stylesheet" href="/css/blog/index.css" />
|
||||||
</head>
|
</head>
|
||||||
<body class="index">
|
<body>
|
||||||
{{#data}}
|
<header>{{>navbar.html}}</header>
|
||||||
|
<main>
|
||||||
|
{{#data}}
|
||||||
|
|
||||||
<h1>Blog</h1>
|
<h1>Blog</h1>
|
||||||
<nav><a id="rss" href="/blog/rss">RSS</a></nav>
|
<p>Blog perso, je dis peut-être n'importe quoi 🫶</p>
|
||||||
<hr />
|
<a id="rss" href="/blog/rss">Lien vers le flux RSS</a>
|
||||||
|
|
||||||
{{#no_posts}}
|
{{#no_posts}}
|
||||||
<h2 class="subtitle" style="text-align: center">Aucun posts</h2>
|
<h2>Aucun posts</h2>
|
||||||
{{/no_posts}} {{^no_posts}}
|
|
||||||
<div class="timeline">
|
{{/no_posts}} {{^no_posts}}
|
||||||
<ul>
|
<ul>
|
||||||
{{#posts}}
|
{{#posts}}
|
||||||
<li onclick="location.href='/blog/p/{{url}}';">
|
<li onclick="window.open('/blog/p/{{url}}', '_parent');">
|
||||||
{{>blog/date.html}}
|
{{>blog/date.html}}
|
||||||
<div class="content">
|
<h2>{{title}}</h2>
|
||||||
<h2>{{title}}</h2>
|
{{#desc}}
|
||||||
{{#desc}}
|
<p>{{desc}}</p>
|
||||||
<p>{{desc}}</p>
|
{{/desc}}
|
||||||
{{/desc}}
|
|
||||||
</div>
|
|
||||||
</li>
|
</li>
|
||||||
{{/posts}}
|
{{/posts}}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
{{/no_posts}} {{/data}}
|
||||||
{{/no_posts}} {{/data}} {{>footer.html}}
|
</main>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html class="index" lang="fr">
|
<html lang="fr">
|
||||||
<head dir="ltr">
|
<head dir="ltr">
|
||||||
{{>blog/head.html}}
|
{{>head.html}}
|
||||||
|
<link
|
||||||
|
rel="alternate"
|
||||||
|
type="application/rss+xml"
|
||||||
|
title="RSS"
|
||||||
|
href="/blog/rss"
|
||||||
|
/>
|
||||||
<link rel="stylesheet" href="/css/blog/post.css" />
|
<link rel="stylesheet" href="/css/blog/post.css" />
|
||||||
{{#data}} {{#post}} {{#metadata}}
|
{{#data}} {{#post}} {{#metadata}}
|
||||||
{{#math}}{{>libs/katex_head.html}}{{/math}}
|
{{#math}}{{>libs/katex_head.html}}{{/math}}
|
||||||
{{#syntax_highlight}}{{>libs/hljs_head.html}}{{/syntax_highlight}}
|
{{#syntax_highlight}}{{>libs/hljs_head.html}}{{/syntax_highlight}}
|
||||||
</head>
|
</head>
|
||||||
<body class="index">
|
<body>
|
||||||
<header>
|
<header>
|
||||||
{{#info}}
|
{{>navbar.html}} {{#info}}
|
||||||
<h1>{{title}}</h1>
|
<h1>{{title}}</h1>
|
||||||
{{#date}} {{>blog/date.html}} {{/date}}
|
{{#date}} {{>blog/date.html}} {{/date}}
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -26,7 +32,7 @@
|
||||||
<article>{{&content}}</article>
|
<article>{{&content}}</article>
|
||||||
{{/post}}
|
{{/post}}
|
||||||
</main>
|
</main>
|
||||||
{{>blog/footer.html}} {{#post}} {{#metadata}}
|
{{#post}} {{#metadata}}
|
||||||
{{#mermaid}}{{>libs/mermaid_footer.html}}{{/mermaid}}
|
{{#mermaid}}{{>libs/mermaid_footer.html}}{{/mermaid}}
|
||||||
{{#math}}{{>libs/katex_footer.html}}{{/math}}
|
{{#math}}{{>libs/katex_footer.html}}{{/math}}
|
||||||
{{#syntax_highlight}}{{>libs/hljs_footer.html}}{{/syntax_highlight}}
|
{{#syntax_highlight}}{{>libs/hljs_footer.html}}{{/syntax_highlight}}
|
||||||
|
|
211
templates/contact.html
Normal file
211
templates/contact.html
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head dir="ltr">
|
||||||
|
{{>head.html}}
|
||||||
|
<link rel="stylesheet" href="/css/contact.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>{{>navbar.html}}</header>
|
||||||
|
<main>
|
||||||
|
<h1>Contact</h1>
|
||||||
|
<p>Je suis présent relativement partout sur internet 😸</p>
|
||||||
|
<h2>Réseaux sociaux</h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Twitter :
|
||||||
|
<a
|
||||||
|
href="/contact/twitter"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer me"
|
||||||
|
title="Compte Twitter, pour le shitposting"
|
||||||
|
>@Mylloon</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Mastodon :
|
||||||
|
<a
|
||||||
|
href="/contact/mastodon"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer me"
|
||||||
|
title="Compte Mastodon, alternative à Twitter, principalement pour l'IT"
|
||||||
|
>Mylloon@piaille.fr</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Discord :
|
||||||
|
<a
|
||||||
|
href="/contact/discord/user"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer me"
|
||||||
|
title="Compte Discord perso"
|
||||||
|
>mylloon</a
|
||||||
|
>
|
||||||
|
et
|
||||||
|
<a
|
||||||
|
href="/contact/discord/guild"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
title="Serveur Discord accessible à tous, venez !"
|
||||||
|
>mon serveur</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Reddit :
|
||||||
|
<a
|
||||||
|
href="/contact/reddit"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer me"
|
||||||
|
title="Compte Reddit, sert à rien"
|
||||||
|
>mylloon</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Instagram :
|
||||||
|
<a
|
||||||
|
href="/contact/instagram"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer me"
|
||||||
|
title="Compte Instagram, sert à rien"
|
||||||
|
>mylloon</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Kitsu :
|
||||||
|
<a
|
||||||
|
href="/contact/kitsu"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer me"
|
||||||
|
title="Compte Kitsu pour tracker d'anime/manga/webtoon"
|
||||||
|
>Mylloon</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Steam :
|
||||||
|
<a
|
||||||
|
href="/contact/steam"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer me"
|
||||||
|
title="Compte Steam pour les jeux-vidéos"
|
||||||
|
>Mylloon</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Youtube :
|
||||||
|
<a
|
||||||
|
href="/contact/youtube"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer me"
|
||||||
|
title="Compte YouTube, parfois je poste des vidéos JV ou IT"
|
||||||
|
>Mylloon</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Twitch :
|
||||||
|
<a
|
||||||
|
href="/contact/twitch"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer me"
|
||||||
|
title="Compte Twitch, parfois je stream soit des JV soit du dev"
|
||||||
|
>mylloon</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Forges</h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Github :
|
||||||
|
<a
|
||||||
|
href="/contact/github"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer me"
|
||||||
|
title="Compte GitHub, principalement pour les contributions"
|
||||||
|
>Mylloon</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Gitlab :
|
||||||
|
<a
|
||||||
|
href="/contact/gitlab"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer me"
|
||||||
|
title="Compte Gitlab, sert à rien"
|
||||||
|
>Mylloon</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Codeberg :
|
||||||
|
<a
|
||||||
|
href="/contact/codeberg"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer me"
|
||||||
|
title="Compte Codeberg, pas utilisé mais j'adore Codeberg !"
|
||||||
|
>Mylloon</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Forgejo (mon instance) :
|
||||||
|
<a
|
||||||
|
href="/contact/forgejo"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer me"
|
||||||
|
title="Compte Forgejo, là où il y a tout mes projets, hébergé par mes soins"
|
||||||
|
>Anri</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Autre</h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Mail :
|
||||||
|
<a
|
||||||
|
href="mailto:kennel.anri%20at%20tutanota.com"
|
||||||
|
title="kennel.anri at tutanota.com"
|
||||||
|
>kennel.anri at tutanota.com</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Keyoxide :
|
||||||
|
<a
|
||||||
|
href="/contact/keyoxide"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer me"
|
||||||
|
title="Page Keyoxide, vérifie l'appartenance de la majorité des comptes mentionné ici via GPG"
|
||||||
|
>Mylloon</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,42 +1,72 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html class="index" lang="fr">
|
<html lang="fr">
|
||||||
<head dir="ltr">
|
<head dir="ltr">
|
||||||
{{>head.html}}
|
{{>head.html}}
|
||||||
|
<link rel="stylesheet" href="/css/contrib.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{{#data}} {{#error}}
|
<header>{{>navbar.html}}</header>
|
||||||
<div id="content">
|
{{#data}}
|
||||||
<p>Github ne veut pas que tu vois ces informations...</p>
|
<main>
|
||||||
</div>
|
<h1>Mes contributions GitHub</h1>
|
||||||
{{/error}} {{^error}}
|
{{#error}}
|
||||||
<div id="content">
|
<p>GitHub ne veut pas que tu vois ces informations...</p>
|
||||||
<h1 class="subtitle">Mes contributions</h1>
|
{{/error}} {{^error}}
|
||||||
<!-- Add URL? -->
|
|
||||||
|
<!-- Add URL of projects repo to projects title? -->
|
||||||
{{#projects}}
|
{{#projects}}
|
||||||
<h2 class="subtitle">{{name}}</h2>
|
<h2>{{name}}</h2>
|
||||||
<p>
|
<ul>
|
||||||
{{#pulls_merged}}
|
{{#pulls_merged}}
|
||||||
<a target="_blank" title="{{title}} " href="{{url}} ">#{{id}}</a>
|
<li>
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<p>
|
||||||
|
<a
|
||||||
|
href="{{url}} "
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
title="{{title}} "
|
||||||
|
>#{{id}}</a></p>
|
||||||
|
</li>
|
||||||
|
|
||||||
{{/pulls_merged}}
|
{{/pulls_merged}}
|
||||||
</p>
|
</ul>
|
||||||
{{/projects}}
|
{{/projects}}
|
||||||
<h1 class="subtitle">En attente</h1>
|
|
||||||
<p>
|
<h1>En attente</h1>
|
||||||
|
<ul>
|
||||||
{{#waiting}} {{#pulls_open}}
|
{{#waiting}} {{#pulls_open}}
|
||||||
<a target="_blank" title="{{title}} " href="{{url}} "
|
<li>
|
||||||
>{{name_repo}}#{{id}}</a
|
<!-- prettier-ignore -->
|
||||||
>
|
<p>
|
||||||
|
<a
|
||||||
|
href="{{url}} "
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
title="{{title}} "
|
||||||
|
>{{name_repo}}#{{id}}</a
|
||||||
|
></p>
|
||||||
|
</li>
|
||||||
{{/pulls_open}} {{/waiting}}
|
{{/pulls_open}} {{/waiting}}
|
||||||
</p>
|
</ul>
|
||||||
<h1 class="subtitle">Non mergées</h1>
|
|
||||||
<p>
|
<h1>Non mergées</h1>
|
||||||
|
<ul>
|
||||||
{{#closed}} {{#pulls_closed}}
|
{{#closed}} {{#pulls_closed}}
|
||||||
<a target="_blank" title="{{title}} " href="{{url}} "
|
<li>
|
||||||
>{{name_repo}}#{{id}}</a
|
<!-- prettier-ignore -->
|
||||||
>
|
<p>
|
||||||
|
<a
|
||||||
|
href="{{url}} "
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
title="{{title}} "
|
||||||
|
>{{name_repo}}#{{id}}</a
|
||||||
|
></p>
|
||||||
|
</li>
|
||||||
{{/pulls_closed}} {{/closed}}
|
{{/pulls_closed}} {{/closed}}
|
||||||
</p>
|
</ul>
|
||||||
</div>
|
</main>
|
||||||
{{/error}} {{/data}} {{>footer.html}}
|
{{/error}} {{/data}}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
<footer class="backToIndexPage">
|
|
||||||
<a href="/">Retour à la page principale</a>
|
|
||||||
</footer>
|
|
|
@ -6,4 +6,5 @@
|
||||||
|
|
||||||
{{>icons.html}} {{>metadata.html}}
|
{{>icons.html}} {{>metadata.html}}
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/css/constants.css" />
|
||||||
<link rel="stylesheet" href="/css/style.css" />
|
<link rel="stylesheet" href="/css/style.css" />
|
||||||
|
|
|
@ -1,14 +1,77 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html class="index" lang="fr">
|
<html lang="fr">
|
||||||
<head dir="ltr">
|
<head dir="ltr">
|
||||||
{{>head.html}}
|
{{>head.html}}
|
||||||
|
<link rel="stylesheet" href="/css/index.css" />
|
||||||
</head>
|
</head>
|
||||||
<body class="index">
|
<body>
|
||||||
<div id="content">
|
<header>{{>navbar.html}}</header>
|
||||||
<p style="font-weight: bold;"><a href="/blog">Blog</a></p>
|
<main>
|
||||||
<p><a href="/portfolio">Portfolio</a></p>
|
{{#data}}
|
||||||
<p><a href="/networks">Réseaux</a></p>
|
|
||||||
<p><a href="/contrib">Contributions</a></p>
|
<div>
|
||||||
<p><a href="https://liv.mylloon.fr">Cours</a> (external)</p>
|
<span id="name">{{fullname}}</span>
|
||||||
|
<span id="pronouns">(il/lui, he/him)</span>
|
||||||
|
<img
|
||||||
|
id="avatar"
|
||||||
|
src="/icons/apple-touch-icon.png"
|
||||||
|
alt="Avatar"
|
||||||
|
title="Mon avatar, dessiné un jour super rapidement sur Gimp."
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p id="subname"></p>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<h1>Bienvenue !</h1>
|
||||||
|
<p>Content de vous voir ici !</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<h1>Qui suis-je ?</h1>
|
||||||
|
<p>Je m'appelle <b>Anri</b>, mon pseudo est <b>Mylloon</b>.</p>
|
||||||
|
<p>
|
||||||
|
J'aime beaucoup l'informatique depuis très petit, ce site est écrit de
|
||||||
|
A à Z par moi-même (modulo la quantité astronomique de librairie
|
||||||
|
utilisé) en Rust. J'adore le monde de l'open source, l'immense
|
||||||
|
majorité de mes projets sont sous licence
|
||||||
|
<a
|
||||||
|
href="https://en.wikipedia.org/wiki/GNU_Affero_General_Public_License"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>AGPLv3</a
|
||||||
|
>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Vous pouvez voir mon <a href="/portfolio">portfolio ici</a>, ainsi que
|
||||||
|
mes <a href="/contrib">contributions sur GitHub ici</a>. Il m'arrive
|
||||||
|
aussi, parfois, d'écrire <a href="/blog">sur mon blog</a>.
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article id="friends">
|
||||||
|
<h1>Personnes incroyables</h1>
|
||||||
|
<a
|
||||||
|
href="https://github.com/2-1-1-2"
|
||||||
|
title="GitHub de 21_12"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
><img src="/badges/friends/21_12.webp" alt="21_12" loading="lazy"
|
||||||
|
/></a>
|
||||||
|
<a
|
||||||
|
href="https://twitter.com/azazouille_"
|
||||||
|
title="Twitter de Azazouille"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
><img
|
||||||
|
src="/badges/friends/azazouille.webp"
|
||||||
|
alt="Azazouille"
|
||||||
|
loading="lazy"
|
||||||
|
/></a>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
{{/data}}
|
||||||
|
</main>
|
||||||
|
<script src="/js/index.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
57
templates/navbar.html
Normal file
57
templates/navbar.html
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
{{#data}}{{#navbar}}
|
||||||
|
<nav>
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
|
||||||
|
<p><a class="_ {{#index}}bold{{/index}}" href="/" title="Page principale"
|
||||||
|
>Infos</a
|
||||||
|
></p>
|
||||||
|
|
||||||
|
</li><li>
|
||||||
|
|
||||||
|
<p><a class="_ {{#blog}}bold{{/blog}}" href="/blog" title="Page de blog"
|
||||||
|
>Blog</a
|
||||||
|
></p>
|
||||||
|
|
||||||
|
</li><li>
|
||||||
|
|
||||||
|
<p><a
|
||||||
|
class="_ {{#portfolio}}bold{{/portfolio}}"
|
||||||
|
href="/portfolio"
|
||||||
|
title="Page du portfolio"
|
||||||
|
>Portfolio</a
|
||||||
|
></p>
|
||||||
|
|
||||||
|
</li><li>
|
||||||
|
|
||||||
|
<p><a
|
||||||
|
class="_ {{#contact}}bold{{/contact}}"
|
||||||
|
href="/contact"
|
||||||
|
title="Page de contact"
|
||||||
|
>Contact</a
|
||||||
|
></p>
|
||||||
|
|
||||||
|
</li><li>
|
||||||
|
|
||||||
|
<p><a
|
||||||
|
class="_ {{#contrib}}bold{{/contrib}}"
|
||||||
|
href="/contrib"
|
||||||
|
title="Page des contributions GitHub"
|
||||||
|
>Contributions</a
|
||||||
|
></p>
|
||||||
|
|
||||||
|
</li><li>
|
||||||
|
|
||||||
|
<p><a
|
||||||
|
class="_ {{#cours}}bold{{/cours}}"
|
||||||
|
href="https://univ.mylloon.fr"
|
||||||
|
title="Page des notes de cours"
|
||||||
|
target="_blank"
|
||||||
|
>Cours</a
|
||||||
|
></p>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
{{/navbar}}{{/data}}
|
|
@ -1,107 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html class="index" lang="fr">
|
|
||||||
<head dir="ltr">
|
|
||||||
{{>head.html}}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="content">
|
|
||||||
<h1 class="subtitle">Contacts et <em>réseaux sociaux</em></h1>
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
rel="me"
|
|
||||||
href="mailto:kennel.anri@tutanota.com"
|
|
||||||
title="kennel dot anri at tutanota dot com"
|
|
||||||
>Email</a
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a target="_blank" rel="me" href="https://twitter.com/Mylloon"
|
|
||||||
>Twitter</a
|
|
||||||
> /
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="me"
|
|
||||||
title="Alternative à Twitter"
|
|
||||||
href="https://piaille.fr/@mylloon"
|
|
||||||
>Mastodon</a
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="me"
|
|
||||||
href="https://discord.com/users/158260864623968257/"
|
|
||||||
>Compte</a
|
|
||||||
> et
|
|
||||||
<a target="_blank" rel="me" href="https://discord.gg/Z5ePxH4">Serveur</a
|
|
||||||
> Discord /
|
|
||||||
<a target="_blank" rel="me" href="https://rvlt.gg/MftpJ98t"
|
|
||||||
>Serveur Revolt</a
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a target="_blank" rel="me" href="https://www.reddit.com/user/mylloon"
|
|
||||||
>Reddit</a
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a target="_blank" rel="me" href="https://www.instagram.com/myshawi/"
|
|
||||||
>Instagram</a
|
|
||||||
> /
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="me"
|
|
||||||
title="Alternative à Instagram"
|
|
||||||
href="https://pixelfed.social/@mylloon"
|
|
||||||
>Pixelfed</a
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a target="_blank" rel="me" href="https://github.com/Mylloon">Github</a
|
|
||||||
> /
|
|
||||||
<a target="_blank" rel="me" href="https://gitlab.com/Mylloon">Gitlab</a
|
|
||||||
> /
|
|
||||||
<a target="_blank" rel="me" href="https://codeberg.org/Mylloon"
|
|
||||||
>Codeberg</a
|
|
||||||
> /
|
|
||||||
<a target="_blank" rel="me" href="https://git.mylloon.fr/Anri"
|
|
||||||
>Mon Git</a
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="me"
|
|
||||||
title="Anime tracker"
|
|
||||||
href="https://kitsu.io/users/Mylloon/library?status=completed"
|
|
||||||
>Kitsu</a
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="me"
|
|
||||||
href="https://steamcommunity.com/id/mylloon/"
|
|
||||||
>Steam</a
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a target="_blank" rel="me" href="https://www.youtube.com/c/Mylloon"
|
|
||||||
>Youtube</a
|
|
||||||
> /
|
|
||||||
<a target="_blank" rel="me" href="https://www.twitch.tv/mylloon"
|
|
||||||
>Twitch</a
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="me"
|
|
||||||
href="https://keyoxide.org/27024A99057E58B8087A5022A82D63DFF8D1317F"
|
|
||||||
>Keyoxide</a
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
{{>footer.html}}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,50 +1,40 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html class="index" lang="fr">
|
<html lang="fr">
|
||||||
<head dir="ltr">
|
<head dir="ltr">
|
||||||
{{>head.html}}
|
{{>head.html}}
|
||||||
|
<link rel="stylesheet" href="/css/portfolio.css" />
|
||||||
|
<link rel="stylesheet" href="/css/languages.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{{#data}}
|
<header>{{>navbar.html}}</header>
|
||||||
<h1 id="title">Projets qui me tiennent à coeur</h1>
|
<main>
|
||||||
<div id="content">
|
{{#data}}
|
||||||
<h2 class="subtitle">Bots</h2>
|
<h1>Portfolio</h1>
|
||||||
<div class="subcontent">
|
<p>
|
||||||
{{#bots_app}} {{#metadata}} {{#info}}
|
Je programme depuis 2018 et j'ai appris une multitude de langages
|
||||||
<h3 class="subsubtitle">
|
depuis. Étant passionné de logiciels libres depuis ma licence
|
||||||
<a target="_blank" href="{{link}} ">{{title}}</a>
|
d'informatique à Paris 8, je publie tout sur des forges publiques.
|
||||||
</h3>
|
</p>
|
||||||
{{/info}} {{/metadata}}
|
|
||||||
<div class="subcontent">{{&content}}</div>
|
|
||||||
{{/bots_app}} {{^bots_app}}
|
|
||||||
<p>{{bots_loc}} {{err_msg}}</p>
|
|
||||||
{{/bots_app}}
|
|
||||||
<br />
|
|
||||||
</div>
|
|
||||||
<h2 class="subtitle">
|
|
||||||
<a target="_blank" href="https://git.mylloon.fr/Paris8"
|
|
||||||
>Projet de l'université</a
|
|
||||||
>
|
|
||||||
</h2>
|
|
||||||
<div class="subcontent">
|
|
||||||
{{&univ_content}} {{^univ_content}}
|
|
||||||
<p>{{univ_loc}} {{err_msg}}</p>
|
|
||||||
{{/univ_content}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 class="subtitle">Projets perso</h2>
|
{{#location_apps}}
|
||||||
<div class="subcontent">
|
<!-- Error message -->
|
||||||
{{#persos_app}} {{#metadata}} {{#info}}
|
<p>{{location_apps}} {{err_msg}}</p>
|
||||||
<h3 class="subsubtitle">
|
{{/location_apps}} {{^location_apps}}
|
||||||
<a target="_blank" href="{{link}} ">{{title}}</a>
|
|
||||||
</h3>
|
<h2>Projets</h2>
|
||||||
{{/info}} {{/metadata}}
|
<ul>
|
||||||
<div class="subcontent">{{&content}}</div>
|
{{#apps}} {{#metadata}} {{#info}}
|
||||||
{{/persos_app}} {{^persos_app}}
|
<li onclick="window.open('{{link}}', '_blank', 'noreferrer');">
|
||||||
<p>{{persos_loc}} {{err_msg}}</p>
|
<div>
|
||||||
{{/persos_app}}
|
<h3>{{title}}</h3>
|
||||||
<br />
|
<span>{{&content}}</span> {{#language}}
|
||||||
</div>
|
<p data-lang="{{language}}"></p>
|
||||||
</div>
|
{{/language}}
|
||||||
{{/data}} {{>footer.html}}
|
</div>
|
||||||
|
</li>
|
||||||
|
{{/info}} {{/metadata}} {{/apps}}
|
||||||
|
</ul>
|
||||||
|
{{/location_apps}} {{/data}}
|
||||||
|
</main>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in a new issue