2024-04-01 18:11:46 +02:00
|
|
|
use std::path::Path;
|
|
|
|
|
|
|
|
use actix_web::{get, web, Responder};
|
|
|
|
use cached::proc_macro::cached;
|
|
|
|
use ramhorns::Content;
|
|
|
|
use regex::Regex;
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
config::Config,
|
|
|
|
misc::{
|
|
|
|
markdown::{File, TypeFileMetadata},
|
|
|
|
utils::{make_kw, read_file, Html},
|
|
|
|
},
|
|
|
|
template::{Infos, NavBar},
|
|
|
|
};
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
pub struct PathRequest {
|
|
|
|
q: Option<String>,
|
|
|
|
}
|
2023-04-16 13:18:15 +02:00
|
|
|
|
|
|
|
#[get("/cours")]
|
2024-04-01 18:11:46 +02:00
|
|
|
async fn page(info: web::Query<PathRequest>, config: web::Data<Config>) -> impl Responder {
|
|
|
|
Html(build_page(info, config.get_ref().to_owned()))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Content, Debug)]
|
|
|
|
struct CoursTemplate {
|
|
|
|
navbar: NavBar,
|
|
|
|
filetree: String,
|
|
|
|
content: Option<File>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize)]
|
|
|
|
struct FileNode {
|
|
|
|
name: String,
|
|
|
|
is_dir: bool,
|
|
|
|
children: Vec<FileNode>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cached]
|
|
|
|
fn compile_patterns(exclusion_list: Vec<String>) -> Vec<Regex> {
|
|
|
|
exclusion_list
|
|
|
|
.iter()
|
|
|
|
.map(|pattern| Regex::new(pattern).unwrap())
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_filetree(dir_path: &str, exclusion_patterns: &Vec<Regex>) -> FileNode {
|
|
|
|
let children = std::fs::read_dir(dir_path)
|
|
|
|
.unwrap()
|
|
|
|
.filter_map(Result::ok)
|
|
|
|
.filter_map(|entry| {
|
|
|
|
let entry_path = entry.path();
|
|
|
|
let entry_name = entry_path.file_name()?.to_string_lossy().to_string();
|
|
|
|
|
|
|
|
// Exclude element with the exclusion_list
|
|
|
|
if exclusion_patterns.iter().any(|re| re.is_match(&entry_name)) {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
if entry_path.is_file() {
|
|
|
|
Some(FileNode {
|
|
|
|
name: entry_name,
|
|
|
|
is_dir: false,
|
|
|
|
children: vec![],
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
// Exclude empty directories
|
|
|
|
let children_of_children =
|
|
|
|
get_filetree(entry_path.to_str().unwrap(), exclusion_patterns);
|
|
|
|
if children_of_children.is_dir && children_of_children.children.is_empty() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(children_of_children)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
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<PathRequest>,
|
|
|
|
exclusion_list: Vec<String>,
|
|
|
|
) -> Option<File> {
|
|
|
|
let filename = match &path.q {
|
|
|
|
Some(q) => q,
|
|
|
|
None => "index.md",
|
|
|
|
};
|
|
|
|
|
|
|
|
// We should support regex?
|
|
|
|
if exclusion_list
|
|
|
|
.iter()
|
|
|
|
.any(|excluded_term| filename.contains(excluded_term.as_str()))
|
|
|
|
{
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
read_file(
|
|
|
|
&format!("{cours_dir}/{filename}"),
|
|
|
|
TypeFileMetadata::Generic,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_page(info: web::Query<PathRequest>, config: Config) -> String {
|
|
|
|
let cours_dir = "data/cours";
|
|
|
|
let exclusion_list = config.fc.exclude_courses.unwrap();
|
|
|
|
let exclusion_patterns = compile_patterns(exclusion_list.to_owned());
|
|
|
|
let filetree = get_filetree(cours_dir, &exclusion_patterns);
|
|
|
|
|
|
|
|
config.tmpl.render(
|
|
|
|
"cours.html",
|
|
|
|
CoursTemplate {
|
|
|
|
navbar: NavBar {
|
|
|
|
cours: true,
|
|
|
|
..NavBar::default()
|
|
|
|
},
|
|
|
|
filetree: serde_json::to_string(&filetree).unwrap(),
|
|
|
|
content: get_content(cours_dir, &info, exclusion_list),
|
|
|
|
},
|
|
|
|
Infos {
|
|
|
|
page_title: Some("Cours".into()),
|
|
|
|
page_desc: Some("Cours à l'univ".into()),
|
|
|
|
page_kw: make_kw(&[
|
|
|
|
"cours",
|
|
|
|
"études",
|
|
|
|
"université",
|
|
|
|
"licence",
|
|
|
|
"master",
|
|
|
|
"notes",
|
|
|
|
"digital garden",
|
|
|
|
]),
|
|
|
|
},
|
|
|
|
)
|
2023-04-16 13:18:15 +02:00
|
|
|
}
|