macroblog.rs @ 0e147a780e74b54afbd56ff7438077d855d5c1c2

 1use chrono::NaiveDate;
 2use pulldown_cmark::{html, Options, Parser};
 3use regex::Regex;
 4use rust_embed::RustEmbed;
 5use sailfish::TemplateOnce;
 6use std::cmp::{Eq, Ord, PartialEq, PartialOrd};
 7use std::str;
 8
 9const BLOG_REGEX: &str = r"(?P<date>[\d]{4}-[\d]{2}-[\d]{2})(?P<title>[a-zA-Z0-9-_]*)";
10
11#[derive(RustEmbed)]
12#[folder = "content/posts/"]
13struct PostAsset;
14
15#[derive(TemplateOnce)]
16#[template(path = "index.html")]
17struct IndexTemplate {
18    posts: Vec<BlogEntry>,
19}
20
21#[derive(TemplateOnce)]
22#[template(path = "post.html")]
23struct PostTemplate {
24    content: String,
25    title: String,
26    date: String,
27}
28
29#[derive(PartialEq, Eq, PartialOrd, Ord)]
30pub struct BlogEntry {
31    pub title: String,
32    pub datetime: NaiveDate,
33    pub file: String,
34}
35
36impl BlogEntry {
37    pub fn new(path: &String) -> BlogEntry {
38        let re = Regex::new(BLOG_REGEX).unwrap();
39        let caps = re.captures(path).unwrap();
40        let date = &caps["date"];
41        let title = str::replace(&caps["title"], "_", " ");
42
43        BlogEntry {
44            title: String::from(title),
45            file: String::from(path),
46            datetime: NaiveDate::parse_from_str(date, "%Y-%m-%d").unwrap(),
47        }
48    }
49
50    pub fn read_assets() -> Vec<BlogEntry> {
51        let mut entries: Vec<BlogEntry> = PostAsset::iter()
52            .map(|e| format!("{}", e))
53            .map(|e| BlogEntry::new(&e))
54            .collect();
55
56        entries.sort_by(|a, b| b.datetime.cmp(&a.datetime));
57
58        entries
59    }
60}
61
62fn get_file_content(path: &str) -> String {
63    let buffer = PostAsset::get(path).unwrap().data.into_owned();
64    let md = String::from_utf8(buffer).unwrap();
65    let parser = Parser::new_ext(&md, Options::empty());
66    let mut html_output = &mut String::new();
67    html::push_html(&mut html_output, parser);
68    return html_output.to_string();
69}
70
71pub fn render_post_page(path: &String) -> String {
72    let blog = BlogEntry::new(path);
73
74    PostTemplate {
75        content: get_file_content(path),
76        title: blog.title,
77        date: blog.datetime.format("%Y-%m-%d").to_string(),
78    }
79    .render_once()
80    .unwrap()
81}
82
83pub fn render_index_page() -> String {
84    IndexTemplate {
85        posts: BlogEntry::read_assets(),
86    }
87    .render_once()
88    .unwrap()
89}