Refactor posts parsing and begin add tags

This commit is contained in:
Florian RICHER 2024-01-06 21:13:10 +01:00
parent 9cd7029ede
commit 51f34eb290
13 changed files with 146 additions and 282 deletions

View file

@ -1,34 +1,43 @@
use serde::{Deserialize, Serialize};
#[derive(Clone, Serialize, Deserialize, Debug)]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PostMetadata {
pub slug: String,
pub image_path: String,
pub title: String,
pub date: String,
pub description: String,
pub project_link: String,
pub draft: bool
pub draft: bool,
pub tags: Vec<String>,
}
#[derive(Clone, Serialize, Deserialize, Debug)]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Post {
pub slug : String,
pub metadata: PostMetadata,
pub content: String,
}
cfg_if::cfg_if! {
if #[cfg(feature = "ssr")] {
impl Post {
fn from_content(content: String) -> Option<Self> {
#[derive(Debug, thiserror::Error)]
pub enum PostDeserializationError {
#[error("Invalid front matter")]
InvalidFrontMatter,
#[error("Invalid markdown")]
InvalidMarkdown,
}
impl TryFrom<String> for Post {
type Error = PostDeserializationError;
fn try_from(content: String) -> Result<Self, Self::Error> {
use gray_matter::{Matter, engine::YAML};
let matter = Matter::<YAML>::new();
let post_data = matter
.parse_with_struct::<PostMetadata>(&content)?;
.parse_with_struct::<PostMetadata>(&content)
.ok_or_else(|| PostDeserializationError::InvalidFrontMatter)?;
let metadata = post_data.data;
let slug = format!("{}_{}", metadata.date, metadata.title.to_lowercase().replace(' ', "_"));
let content = post_data.content;
use pulldown_cmark::{Parser, Options, html};
@ -36,49 +45,14 @@ cfg_if::cfg_if! {
let mut html_output = String::new();
html::push_html(&mut html_output, parser);
Some(Self {
slug,
metadata,
content: html_output,
})
}
fn from_path(path: &std::path::Path) -> Option<Self> {
let content = std::fs::read_to_string(path);
let content = match content {
Ok(content) => content,
Err(e) => {
eprintln!("{:?}", e);
return None;
}
};
Self::from_content(content)
}
pub fn get_all(folder: &str) -> Result<Vec<Self>, String> {
use std::{path::Path, fs::read_dir};
let mut posts: Vec<Self> = Vec::new();
let folder_path = Path::new("data_src").join(folder);
let paths = read_dir(folder_path).map_err(|e| e.to_string())?;
for path_result in paths {
let path = match path_result {
Ok(path) => path.path(),
Err(e) => {
eprintln!("{:?}", e);
continue;
}
};
if let Some(post) = Self::from_path(&path) {
posts.push(post);
}
if html_output.is_empty() {
return Err(PostDeserializationError::InvalidMarkdown);
}
Ok(posts)
Ok(Self {
metadata: post_data.data,
content: html_output,
})
}
}
}