diff --git a/src/misc/markdown.rs b/src/misc/markdown.rs index 1a18509..a1f2e86 100644 --- a/src/misc/markdown.rs +++ b/src/misc/markdown.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Deserializer}; use std::fs; #[derive(Default, Deserialize, Content, Debug)] -pub struct FileMetadata { +pub struct FileMetadataBlog { pub title: Option, pub link: Option, pub date: Option, @@ -17,6 +17,37 @@ pub struct FileMetadata { pub language: Option, } +#[derive(Default, Deserialize, Content, Debug)] +pub struct FileMetadataContact { + pub title: String, + pub custom: Option, + pub user: Option, + pub link: Option, + pub newtab: Option, + pub description: Option, +} + +#[derive(Default, Deserialize, Content, Debug)] +pub struct FileMetadataPortfolio { + pub title: Option, + pub link: Option, + pub description: Option, + pub language: Option, +} + +pub enum TypeFileMetadata { + Blog, + Contact, + Portfolio, +} + +#[derive(Default, Deserialize, Content, Debug)] +pub struct FileMetadata { + pub blog: Option, + pub contact: Option, + pub portfolio: Option, +} + #[derive(Content, Debug, Clone)] pub struct Tag { pub name: String, @@ -87,14 +118,14 @@ pub fn get_options() -> ComrakOptions { } /// Transform markdown string to File structure -fn read(raw_text: &str) -> File { +fn read(raw_text: &str, metadata_type: TypeFileMetadata) -> File { let arena = Arena::new(); let options = get_options(); let root = parse_document(&arena, raw_text, &options); // Find metadata - let metadata = get_metadata(root); + let metadata = get_metadata(root, metadata_type); let mermaid_name = "mermaid"; hljs_replace(root, mermaid_name); @@ -117,26 +148,54 @@ fn read(raw_text: &str) -> File { } /// Read markdown file -pub fn read_file(filename: &str) -> Option { +pub fn read_file(filename: &str, expected_file: TypeFileMetadata) -> Option { match fs::read_to_string(filename) { - Ok(text) => Some(read(&text)), + Ok(text) => Some(read(&text, expected_file)), _ => None, } } +/// Deserialize metadata based on a type +fn deserialize_metadata(text: &str) -> T { + serde_yaml::from_str(text.trim_matches(&['-', '\n'] as &[_])).unwrap_or_default() +} + /// Fetch metadata from AST -pub fn get_metadata<'a>(root: &'a AstNode<'a>) -> FileMetadata { +pub fn get_metadata<'a>(root: &'a AstNode<'a>, mtype: TypeFileMetadata) -> FileMetadata { match root .children() .find_map(|node| match &node.data.borrow().value { - NodeValue::FrontMatter(text) => { - // '-' correspond to `front_matter_delimiter` - serde_yaml::from_str(text.trim_matches(&['-', '\n'] as &[_])).unwrap_or_default() - } + NodeValue::FrontMatter(text) => Some(match mtype { + TypeFileMetadata::Blog => FileMetadata { + blog: Some(deserialize_metadata(text)), + ..FileMetadata::default() + }, + TypeFileMetadata::Contact => FileMetadata { + contact: Some(deserialize_metadata(text)), + ..FileMetadata::default() + }, + TypeFileMetadata::Portfolio => FileMetadata { + portfolio: Some(deserialize_metadata(text)), + ..FileMetadata::default() + }, + }), _ => None, }) { Some(data) => data, - None => FileMetadata::default(), + None => match mtype { + TypeFileMetadata::Blog => FileMetadata { + blog: Some(FileMetadataBlog::default()), + ..FileMetadata::default() + }, + TypeFileMetadata::Contact => FileMetadata { + contact: Some(FileMetadataContact::default()), + ..FileMetadata::default() + }, + TypeFileMetadata::Portfolio => FileMetadata { + portfolio: Some(FileMetadataPortfolio::default()), + ..FileMetadata::default() + }, + }, } } diff --git a/src/routes/blog.rs b/src/routes/blog.rs index 66482d1..f5e26c4 100644 --- a/src/routes/blog.rs +++ b/src/routes/blog.rs @@ -18,7 +18,9 @@ use crate::{ config::Config, misc::{ date::Date, - markdown::{get_metadata, get_options, read_file, File, FileMetadata}, + markdown::{ + get_metadata, get_options, read_file, File, FileMetadataBlog, TypeFileMetadata, + }, utils::get_url, }, template::{Infos, NavBar}, @@ -87,7 +89,10 @@ impl Post { let blog_dir = "data/blog"; let ext = ".md"; - if let Some(file) = read_file(&format!("{blog_dir}/{}{ext}", self.url)) { + if let Some(file) = read_file( + &format!("{blog_dir}/{}{ext}", self.url), + TypeFileMetadata::Blog, + ) { self.content = Some(file.content); } } @@ -126,7 +131,7 @@ fn get_posts(location: &str) -> Vec { let options = get_options(); let root = parse_document(&arena, &text, &options); - let mut metadata = get_metadata(root); + let mut metadata = get_metadata(root, TypeFileMetadata::Blog).blog.unwrap(); // Always have a title metadata.title = match metadata.title { @@ -136,9 +141,9 @@ fn get_posts(location: &str) -> Vec { metadata } - Err(_) => FileMetadata { + Err(_) => FileMetadataBlog { title: Some(file_without_ext.into()), - ..FileMetadata::default() + ..FileMetadataBlog::default() }, }; @@ -222,20 +227,23 @@ fn get_post( let blog_dir = "data/blog"; let ext = ".md"; - *post = read_file(&format!("{blog_dir}/{filename}{ext}")); + *post = read_file( + &format!("{blog_dir}/{filename}{ext}"), + TypeFileMetadata::Blog, + ); let default = (&filename, Vec::new(), String::new()); let (title, tags, toc) = match post { Some(data) => ( - match &data.metadata.info.title { + match &data.metadata.info.blog.as_ref().unwrap().title { Some(text) => text, None => default.0, }, - match &data.metadata.info.tags { + match &data.metadata.info.blog.as_ref().unwrap().tags { Some(tags) => tags.clone(), None => default.1, }, - match &data.metadata.info.toc { + match &data.metadata.info.blog.as_ref().unwrap().toc { // TODO: Generate TOC Some(true) => String::new(), _ => default.2, diff --git a/src/routes/contact.rs b/src/routes/contact.rs index 6440cc8..db2e114 100644 --- a/src/routes/contact.rs +++ b/src/routes/contact.rs @@ -1,10 +1,14 @@ use actix_web::{get, routes, web, HttpRequest, HttpResponse, Responder}; use cached::proc_macro::once; +use glob::glob; use ramhorns::Content; use crate::{ config::Config, - misc::utils::get_url, + misc::{ + markdown::{read_file, File, TypeFileMetadata}, + utils::get_url, + }, template::{Infos, NavBar}, }; @@ -63,17 +67,65 @@ async fn service_redirection(req: HttpRequest) -> impl Responder { #[derive(Content, Debug)] struct NetworksTemplate { navbar: NavBar, + + socials_exists: bool, + socials: Vec, + + forges_exists: bool, + forges: Vec, + + others_exists: bool, + others: Vec, +} + +fn remove_paragraphs(list: &mut [File]) { + list.iter_mut() + .for_each(|file| file.content = file.content.replace("

", "").replace("

", "")); } #[once(time = 60)] fn build_page(config: Config, url: String) -> String { + let contacts_dir = "data/contacts"; + let ext = ".md"; + + let socials_dir = "socials"; + let mut socials = glob(&format!("{contacts_dir}/{socials_dir}/*{ext}")) + .unwrap() + .map(|e| read_file(&e.unwrap().to_string_lossy(), TypeFileMetadata::Contact).unwrap()) + .collect::>(); + + let forges_dir = "forges"; + let mut forges = glob(&format!("{contacts_dir}/{forges_dir}/*{ext}")) + .unwrap() + .map(|e| read_file(&e.unwrap().to_string_lossy(), TypeFileMetadata::Contact).unwrap()) + .collect::>(); + + let others_dir = "others"; + let mut others = glob(&format!("{contacts_dir}/{others_dir}/*{ext}")) + .unwrap() + .map(|e| read_file(&e.unwrap().to_string_lossy(), TypeFileMetadata::Contact).unwrap()) + .collect::>(); + + // Remove paragraphs in custom statements + [&mut socials, &mut forges, &mut others] + .iter_mut() + .for_each(|it| remove_paragraphs(it)); + config.tmpl.render( - "contact.html", + "contact/index.html", NetworksTemplate { navbar: NavBar { contact: true, ..NavBar::default() }, + socials_exists: !socials.is_empty(), + socials, + + forges_exists: !forges.is_empty(), + forges, + + others_exists: !others.is_empty(), + others, }, Infos { page_title: Some("Contacts".into()), diff --git a/src/routes/portfolio.rs b/src/routes/portfolio.rs index 0df913d..953df52 100644 --- a/src/routes/portfolio.rs +++ b/src/routes/portfolio.rs @@ -6,7 +6,7 @@ use ramhorns::Content; use crate::{ config::Config, misc::{ - markdown::{read_file, File}, + markdown::{read_file, File, TypeFileMetadata}, utils::get_url, }, template::{Infos, NavBar}, @@ -38,7 +38,7 @@ fn build_page(config: Config, url: String) -> String { // Get apps let apps = glob(&format!("{projects_dir}/*{ext}")) .unwrap() - .map(|e| read_file(&e.unwrap().to_string_lossy()).unwrap()) + .map(|e| read_file(&e.unwrap().to_string_lossy(), TypeFileMetadata::Portfolio).unwrap()) .collect::>(); let appdata = if apps.is_empty() { @@ -50,7 +50,7 @@ fn build_page(config: Config, url: String) -> String { // Get archived apps let archived_apps = glob(&format!("{projects_dir}/archive/*{ext}")) .unwrap() - .map(|e| read_file(&e.unwrap().to_string_lossy()).unwrap()) + .map(|e| read_file(&e.unwrap().to_string_lossy(), TypeFileMetadata::Portfolio).unwrap()) .collect::>(); let archived_appdata = if archived_apps.is_empty() { diff --git a/static/css/contact.css b/static/css/contact.css index 3d6c9a0..3f3ad64 100644 --- a/static/css/contact.css +++ b/static/css/contact.css @@ -15,6 +15,10 @@ main ul { column-gap: 5em; } +main li { + break-inside: avoid-column; +} + main li > p { margin: 0; padding: 3%; diff --git a/templates/blog/post.html b/templates/blog/post.html index 2182d9d..188f49c 100644 --- a/templates/blog/post.html +++ b/templates/blog/post.html @@ -15,7 +15,7 @@
- {{>navbar.html}} {{#info}} + {{>navbar.html}} {{#info}} {{#blog}}

{{title}}

{{#date}} {{>blog/date.html}} {{/date}}
    @@ -23,7 +23,7 @@
  • {{name}}
  • {{/tags}}
- {{/info}} {{/metadata}} {{/post}} + {{/blog}} {{/info}} {{/metadata}} {{/post}}
{{^post}} diff --git a/templates/contact.html b/templates/contact.html deleted file mode 100644 index 73ed0f2..0000000 --- a/templates/contact.html +++ /dev/null @@ -1,223 +0,0 @@ - - - - {{>head.html}} - - - -
{{>navbar.html}}
-
-

Contact

-

Je suis présent relativement partout sur internet 😸

-

Réseaux sociaux

- - -

Forges

-
    -
  • -

    - Github : - Mylloon -

    -
  • -
  • -

    - Gitlab : - Mylloon -

    -
  • -
  • -

    - Codeberg : - Mylloon -

    -
  • -
  • -

    - Forgejo (mon instance) : - Anri -

    -
  • -
- -

Autre

- -
- - diff --git a/templates/contact/element.html b/templates/contact/element.html new file mode 100644 index 0000000..98c446b --- /dev/null +++ b/templates/contact/element.html @@ -0,0 +1,17 @@ +{{#metadata}} {{#info}} {{#contact}} +
  • +

    + {{title}} : {{^custom}} {{#newtab}} + {{user}} + {{/newtab}} {{^newtab}} + {{user}} + {{/newtab}} {{/custom}} {{#custom}} {{&content}} {{/custom}} +

    +
  • +{{/contact}} {{/info}} {{/metadata}} diff --git a/templates/contact/index.html b/templates/contact/index.html new file mode 100644 index 0000000..cbd8e5e --- /dev/null +++ b/templates/contact/index.html @@ -0,0 +1,31 @@ + + + + {{>head.html}} + + + +
    {{>navbar.html}}
    +
    +

    Contact

    +

    Je suis présent relativement partout sur internet 😸

    + + {{#data}} {{#socials_exists}} +

    Réseaux sociaux

    +
      + {{#socials}} {{>contact/element.html}} {{/socials}} +
    + {{/socials_exists}} {{#forges_exists}} +

    Forges

    +
      + {{#forges}} {{>contact/element.html}} {{/forges}} +
    + {{/forges_exists}} {{#others_exists}} +

    Autre

    +
      + {{#others}} {{>contact/element.html}} {{/others}} +
    + {{/others_exists}} {{/data}} +
    + + diff --git a/templates/portfolio/card.html b/templates/portfolio/card.html index c7459dc..8a0ad6d 100644 --- a/templates/portfolio/card.html +++ b/templates/portfolio/card.html @@ -1,7 +1,7 @@ -{{#metadata}} {{#info}} {{#link}} +{{#metadata}} {{#info}} {{#portfolio}} {{#link}}
  • {{>portfolio/project.html}}
  • {{/link}} {{^link}}
  • {{>portfolio/project.html}}
  • -{{/link}} {{/info}} {{/metadata}} +{{/link}} {{/portfolio}} {{/info}} {{/metadata}}