Merge pull request 'feat: allow subdirs in posts directory' (#86) from posts-subdir into main

Reviewed-on: #86
This commit is contained in:
Mylloon 2024-11-14 17:48:07 +01:00
commit 4ae660983f
Signed by: Forgejo
GPG key ID: E72245C752A07631
9 changed files with 38 additions and 52 deletions

1
Cargo.lock generated
View file

@ -1095,6 +1095,7 @@ dependencies = [
"serde_yml", "serde_yml",
"toml", "toml",
"urlencoding", "urlencoding",
"walkdir",
] ]
[[package]] [[package]]

View file

@ -32,6 +32,7 @@ mime_guess = "2.0"
urlencoding = "2.1" urlencoding = "2.1"
regex = "1.10" regex = "1.10"
cyborgtime = "2.1.1" cyborgtime = "2.1.1"
walkdir = "2.5"
[lints.clippy] [lints.clippy]
pedantic = "warn" pedantic = "warn"

View file

@ -13,8 +13,8 @@ use crate::routes::{
mod config; mod config;
mod template; mod template;
mod utils;
mod routes; mod routes;
mod utils;
#[actix_web::main] #[actix_web::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {

View file

@ -1,4 +1,4 @@
use crate::{config::Config, utils::misc::get_url, template::InfosPage}; use crate::{config::Config, template::InfosPage, utils::misc::get_url};
use actix_web::{get, http::header::ContentType, routes, web, HttpResponse, Responder}; use actix_web::{get, http::header::ContentType, routes, web, HttpResponse, Responder};
use cached::proc_macro::once; use cached::proc_macro::once;
use ramhorns::Content; use ramhorns::Content;

View file

@ -67,7 +67,7 @@ struct BlogPostTemplate {
toc: String, toc: String,
} }
#[get("/blog/p/{id}")] #[get("/blog/p/{id:.*}")]
pub async fn page(path: web::Path<(String,)>, config: web::Data<Config>) -> impl Responder { pub async fn page(path: web::Path<(String,)>, config: web::Data<Config>) -> impl Responder {
Html(build_post( Html(build_post(
&path.into_inner().0, &path.into_inner().0,

View file

@ -4,8 +4,8 @@ use ramhorns::Content;
use crate::{ use crate::{
config::Config, config::Config,
utils::misc::{get_url, Html},
template::{InfosPage, NavBar}, template::{InfosPage, NavBar},
utils::misc::{get_url, Html},
}; };
pub async fn page(config: web::Data<Config>) -> impl Responder { pub async fn page(config: web::Data<Config>) -> impl Responder {

View file

@ -36,21 +36,12 @@ fn build_page(config: Config) -> String {
let ext = ".md"; let ext = ".md";
// Get about // Get about
let about = read_file( let about = read_file(format!("{projects_dir}/about.md"), MType::Generic);
format!("{projects_dir}/about.md"),
MType::Generic,
);
// Get apps // Get apps
let apps = glob(&format!("{apps_dir}/*{ext}")) let apps = glob(&format!("{apps_dir}/*{ext}"))
.unwrap() .unwrap()
.map(|e| { .map(|e| read_file(e.unwrap().to_string_lossy().to_string(), MType::Portfolio).unwrap())
read_file(
e.unwrap().to_string_lossy().to_string(),
MType::Portfolio,
)
.unwrap()
})
.collect::<Vec<File>>(); .collect::<Vec<File>>();
let appdata = if apps.is_empty() { let appdata = if apps.is_empty() {
@ -62,13 +53,7 @@ fn build_page(config: Config) -> String {
// Get archived apps // Get archived apps
let archived_apps = glob(&format!("{apps_dir}/archive/*{ext}")) let archived_apps = glob(&format!("{apps_dir}/archive/*{ext}"))
.unwrap() .unwrap()
.map(|e| { .map(|e| read_file(e.unwrap().to_string_lossy().to_string(), MType::Portfolio).unwrap())
read_file(
e.unwrap().to_string_lossy().to_string(),
MType::Portfolio,
)
.unwrap()
})
.collect::<Vec<File>>(); .collect::<Vec<File>>();
let archived_appdata = if archived_apps.is_empty() { let archived_appdata = if archived_apps.is_empty() {

View file

@ -3,8 +3,8 @@ use cached::proc_macro::once;
use crate::{ use crate::{
config::Config, config::Config,
utils::misc::{make_kw, Html},
template::InfosPage, template::InfosPage,
utils::misc::{make_kw, Html},
}; };
#[get("/web3")] #[get("/web3")]

View file

@ -12,6 +12,7 @@ use chrono::{DateTime, Datelike, Local, NaiveDateTime, Utc};
use chrono_tz::Europe; use chrono_tz::Europe;
use comrak::{parse_document, Arena}; use comrak::{parse_document, Arena};
use ramhorns::Content; use ramhorns::Content;
use walkdir::WalkDir;
use crate::{ use crate::{
config::Config, config::Config,
@ -59,46 +60,44 @@ impl Hash for Post {
} }
pub fn get_posts(location: &str) -> Vec<Post> { pub fn get_posts(location: &str) -> Vec<Post> {
std::fs::read_dir(location) WalkDir::new(location)
.map_or_else( .into_iter()
|_| vec![], .filter_map(Result::ok)
|res| { .filter(|entry| {
res.flatten() entry.file_type().is_file() && entry.path().extension().is_some_and(|s| s == "md")
.filter(|f| f.path().extension().map_or(false, |ext| ext == "md")) })
.collect::<Vec<std::fs::DirEntry>>()
},
)
.iter()
.filter_map(|f| { .filter_map(|f| {
let fname = f.file_name(); let fname = f.file_name();
let filename = fname.to_string_lossy(); let filename = fname.to_string_lossy();
let file_without_ext = filename.split_at(filename.len() - 3).0; let file_without_ext = filename.split_at(filename.len() - 3).0;
let file_metadata = std::fs::read_to_string(format!("{location}/{filename}")) let file_metadata = std::fs::read_to_string(f.path()).map_or_else(
.map_or_else( |_| FileMetadataBlog {
|_| FileMetadataBlog { title: Some(file_without_ext.into()),
title: Some(file_without_ext.into()), ..FileMetadataBlog::default()
..FileMetadataBlog::default() },
}, |text| {
|text| { let arena = Arena::new();
let arena = Arena::new();
let options = get_options(); let options = get_options();
let root = parse_document(&arena, &text, &options); let root = parse_document(&arena, &text, &options);
let mut metadata = get(root, MType::Blog).blog.unwrap(); let mut metadata = get(root, MType::Blog).blog.unwrap();
// Always have a title // Always have a title
metadata.title = metadata metadata.title = metadata
.title .title
.map_or_else(|| Some(file_without_ext.into()), Some); .map_or_else(|| Some(file_without_ext.into()), Some);
metadata metadata
}, },
); );
if file_metadata.publish == Some(true) && file_metadata.draft != Some(true) { if file_metadata.publish == Some(true) && file_metadata.draft != Some(true) {
let url =
f.path().to_string_lossy().strip_prefix(location).unwrap()[1..].to_owned();
Some(Post { Some(Post {
url: file_without_ext.into(), url: url[..url.len() - 3].to_owned(),
title: file_metadata.title.unwrap(), title: file_metadata.title.unwrap(),
date: file_metadata.date.unwrap_or({ date: file_metadata.date.unwrap_or({
let m = f.metadata().unwrap(); let m = f.metadata().unwrap();