From d025981f0ef9b65a2292632948ac8381b332a9e7 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Wed, 1 Nov 2023 03:36:03 +0100 Subject: [PATCH] filetree preparation --- Cargo.lock | 1 + Cargo.toml | 1 + src/misc/markdown.rs | 19 ++++++----- src/routes/cours.rs | 78 ++++++++++++++++++++++++++++++++++++-------- static/js/cours.js | 4 +++ templates/cours.html | 10 ++++-- 6 files changed, 88 insertions(+), 25 deletions(-) create mode 100644 static/js/cours.js diff --git a/Cargo.lock b/Cargo.lock index 63a927f..c69c76b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -930,6 +930,7 @@ dependencies = [ "reqwest", "rss", "serde", + "serde_json", "serde_yaml", "toml", ] diff --git a/Cargo.toml b/Cargo.toml index 221886a..ae424b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ ramhorns = "0.14" toml = "0.8" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.9" +serde_json = "1.0" minify-html = "0.11" minify-js = "0.5" glob = "0.3" diff --git a/src/misc/markdown.rs b/src/misc/markdown.rs index 9ba2aaf..bba0e42 100644 --- a/src/misc/markdown.rs +++ b/src/misc/markdown.rs @@ -6,7 +6,11 @@ use ramhorns::Content; use serde::{Deserialize, Deserializer}; use std::fs; -#[derive(Default, Deserialize, Content, Debug)] +/// Regular markdown files, no metadata +#[derive(Content, Debug, Default, Deserialize)] +pub struct FileNoMetadata {} + +#[derive(Content, Debug, Default, Deserialize)] pub struct FileMetadataBlog { pub title: Option, pub date: Option, @@ -16,7 +20,7 @@ pub struct FileMetadataBlog { pub toc: Option, } -#[derive(Default, Deserialize, Content, Debug)] +#[derive(Content, Debug, Default, Deserialize)] pub struct FileMetadataContact { pub title: String, pub custom: Option, @@ -26,7 +30,7 @@ pub struct FileMetadataContact { pub description: Option, } -#[derive(Default, Deserialize, Content, Debug)] +#[derive(Content, Debug, Default, Deserialize)] pub struct FileMetadataPortfolio { pub title: Option, pub link: Option, @@ -34,9 +38,6 @@ pub struct FileMetadataPortfolio { pub language: Option, } -#[derive(Default, Deserialize, Content, Debug)] -pub struct FileMetadataCours {} - pub enum TypeFileMetadata { Blog, Contact, @@ -44,12 +45,12 @@ pub enum TypeFileMetadata { Cours, } -#[derive(Default, Deserialize, Content, Debug)] +#[derive(Content, Debug, Default, Deserialize)] pub struct FileMetadata { pub blog: Option, pub contact: Option, pub portfolio: Option, - pub cours: Option, + pub cours: Option, } #[derive(Content, Debug, Clone)] @@ -254,7 +255,7 @@ pub fn get_metadata<'a>(root: &'a AstNode<'a>, mtype: TypeFileMetadata) -> FileM ..FileMetadata::default() }, TypeFileMetadata::Cours => FileMetadata { - cours: Some(FileMetadataCours::default()), + cours: Some(FileNoMetadata::default()), ..FileMetadata::default() }, }, diff --git a/src/routes/cours.rs b/src/routes/cours.rs index 1ce7074..0f18f0f 100644 --- a/src/routes/cours.rs +++ b/src/routes/cours.rs @@ -1,43 +1,91 @@ +use std::path::Path; + use actix_web::{get, web, Responder}; -use glob::glob; use ramhorns::Content; +use serde::{Deserialize, Serialize}; use crate::{ config::Config, misc::{ - markdown::{read_file, TypeFileMetadata}, + markdown::{read_file, File, TypeFileMetadata}, utils::{make_kw, Html}, }, template::{Infos, NavBar}, }; +#[derive(Debug, Deserialize)] +pub struct PathRequest { + q: Option, +} + #[get("/cours")] -async fn page(config: web::Data) -> impl Responder { - Html(build_page(config.get_ref().to_owned())) +async fn page(info: web::Query, config: web::Data) -> impl Responder { + Html(build_page(info, config.get_ref().to_owned())) } #[derive(Content, Debug)] struct CoursTemplate { navbar: NavBar, - /* filetree: Truc, */ + filetree: String, + content: Option, } -/// Get the filetree -fn get_filetree() { - let cours_dir = "data/cours"; - glob(&format!("{cours_dir}/*")).unwrap(); +#[derive(Serialize)] +struct FileNode { + name: String, + is_dir: bool, + children: Vec, } -/// Get a page -fn get_page(filename: &str) { - let cours_dir = "data/cours"; +/// Build the filetree +fn get_filetree(dir_path: &str, exclusion_list: &[&str]) -> FileNode { + let entries = std::fs::read_dir(dir_path).unwrap(); - let post = read_file(&format!("{cours_dir}/{filename}"), TypeFileMetadata::Cours); + let mut children = Vec::new(); + for entry in entries.filter_map(Result::ok) { + let entry_path = entry.path(); + let entry_name = entry_path.file_name().and_then(|n| n.to_str()).unwrap(); + if !exclusion_list.contains(&entry_name) { + let filename = entry_name.to_string(); + if entry_path.is_file() { + children.push(FileNode { + name: filename, + is_dir: false, + children: vec![], + }); + } else { + children.push(get_filetree(entry_path.to_str().unwrap(), exclusion_list)); + } + } + } + + FileNode { + name: Path::new(dir_path) + .file_name() + .unwrap() + .to_string_lossy() + .to_string(), + is_dir: true, + children, + } +} + +/// Get a page content +fn get_content(cours_dir: &str, path: &web::Query) -> Option { + let filename = match &path.q { + Some(q) => q, + None => "index.md", + }; + + read_file(&format!("{cours_dir}/{filename}"), TypeFileMetadata::Cours) } // #[once(time = 60)] // TODO: Uncomment before release -fn build_page(config: Config) -> String { +fn build_page(info: web::Query, config: Config) -> String { + let cours_dir = "data/cours"; + let filetree = get_filetree(cours_dir, &[]); + config.tmpl.render( "cours.html", CoursTemplate { @@ -45,6 +93,8 @@ fn build_page(config: Config) -> String { cours: true, ..NavBar::default() }, + filetree: serde_json::to_string(&filetree).unwrap(), + content: get_content(cours_dir, &info), }, Infos { page_title: Some("Cours".into()), diff --git a/static/js/cours.js b/static/js/cours.js new file mode 100644 index 0000000..e52ecf0 --- /dev/null +++ b/static/js/cours.js @@ -0,0 +1,4 @@ +window.addEventListener("load", () => { + /* Ici on va récuperer le JSON envoyer par le serveur et le transformer + * en un jolie filetree */ +}); diff --git a/templates/cours.html b/templates/cours.html index 79e33ee..dd4c461 100644 --- a/templates/cours.html +++ b/templates/cours.html @@ -9,9 +9,15 @@
{{#data}} -

Coucou

+ - {{/data}} + {{^content}} +

Fichier introuvable

+ {{/content}} {{#content}} +
{{&content}}
+ {{/content}} {{/data}}