use serde::{Deserialize, Serialize}; #[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 tags: Vec, } #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Post { pub metadata: PostMetadata, pub content: String, } cfg_if::cfg_if! { if #[cfg(feature = "ssr")] { #[derive(Debug, thiserror::Error)] pub enum PostDeserializationError { #[error("Invalid front matter")] InvalidFrontMatter, #[error("Invalid markdown")] InvalidMarkdown, } impl TryFrom for Post { type Error = PostDeserializationError; fn try_from(content: String) -> Result { use gray_matter::{Matter, engine::YAML}; let matter = Matter::::new(); let post_data = matter .parse_with_struct::(&content) .ok_or_else(|| PostDeserializationError::InvalidFrontMatter)?; let content = post_data.content; use pulldown_cmark::{Parser, Options, html}; let parser = Parser::new_ext(&content, Options::all()); let mut html_output = String::new(); html::push_html(&mut html_output, parser); if html_output.is_empty() { return Err(PostDeserializationError::InvalidMarkdown); } Ok(Self { metadata: post_data.data, content: html_output, }) } } } }