aboutsummaryrefslogblamecommitdiffstats
path: root/src/blog.rs
blob: b6ca75cdc79cb302cf0f92a6177385eab05e7cee (plain) (tree)
1
2
3
4
5
6
7
8
9








                                                                               
                     




                            
                                      


















                                      

























                                                                                                   












                                              

                                                    

     

                                                


















                                     
 
use std::path::Path;

use markdown::{mdast::Node, CompileOptions, Constructs, Options, ParseOptions};
use serde::Deserialize;
use tokio::{fs, io::AsyncReadExt};

use chrono::{DateTime, Utc};

use crate::{
    article::Article,
    error::BlossomError,
    posts::{Post, PostType},
    Result,
};

static DIRECTORY: &str = "./articles";

#[derive(Clone)]
pub struct Blogpost {
    file_name: String,
    title: String,
    published_at: DateTime<Utc>,
    updated_at: Option<DateTime<Utc>>,
    tags: Vec<String>,
    content: String,
}

#[derive(Deserialize)]
pub struct BlogpostMetadata {
    title: String,
    published_at: String,
    updated_at: Option<String>,
    tags: Vec<String>,
}

impl Article for Blogpost {
    type Metadata = BlogpostMetadata;

    type Article = Blogpost;

    fn directory() -> &'static str {
        DIRECTORY
    }

    fn new(file_name: String, metadata: Self::Metadata, content: String) -> Result<Self::Article> {
        let updated_at = if let Some(updated_at) = metadata.updated_at {
            Some(updated_at.parse::<DateTime<Utc>>()?)
        } else {
            None
        };
        Ok(Blogpost {
            file_name,
            title: metadata.title,
            published_at: metadata.published_at.parse::<DateTime<Utc>>()?,
            updated_at,
            tags: metadata.tags,
            content,
        })
    }
}

impl Post for Blogpost {
    fn id(&self) -> &str {
        &self.file_name
    }

    fn subject(&self) -> Option<&str> {
        Some(&self.title)
    }

    fn published_at(&self) -> &DateTime<Utc> {
        &self.published_at
    }

    fn updated_at(&self) -> Option<&DateTime<Utc>> {
        self.updated_at.as_ref()
    }

    fn tags(&self) -> Vec<&str> {
        self.tags.iter().map(|s| &**s).collect()
    }

    fn lang(&self) -> &str {
        "en"
    }

    fn post_type(&self) -> PostType {
        PostType::Article
    }

    fn content(&self) -> &str {
        &self.content
    }
}

impl Blogpost {
    pub fn file_name(&self) -> &str {
        &self.file_name
    }
}