[ MIRROR ] A small, fast, static site generator git.ngill.net/tars.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112use anyhow::Result;use chrono::NaiveDate;use pulldown_cmark::{Options, Parser};use serde::{Deserialize, Serialize};use std::fs;use std::path::{Path, PathBuf};
use crate::config::Config;
#[derive(Debug, Serialize, Deserialize)]pub struct FrontMatter { pub title: Option<String>, pub date: Option<NaiveDate>, pub author: Option<String>, #[serde(rename(serialize = "type", deserialize = "type"))] pub page_type: Option<String>, #[serde(default)] pub draft: bool, pub template: Option<String>, pub tags: Option<Vec<String>>, pub slug: Option<String>, pub summary: Option<String>, pub cover_image: Option<String>,}
impl FrontMatter { pub fn merge_with_default(&self, config: &Config) -> Self { Self { title: self.title.clone(), date: self.date, author: self.author.clone(), page_type: self.page_type.clone(), draft: self.draft, template: self .template .clone() .or(Some(config.site.default_template.clone())), tags: self.tags.clone(), slug: self.slug.clone(), summary: self.summary.clone(), cover_image: self.cover_image.clone(), } }
fn new(config: &Config) -> Self { Self { title: None, date: None, author: None, page_type: None, draft: false, template: Some(config.site.default_template.clone()), tags: None, slug: None, summary: None, cover_image: None, } }}
#[derive(Debug, Serialize, Deserialize)]pub struct Page { #[serde(skip)] pub path: PathBuf, #[serde(rename(serialize = "path"))] pub rel_path: PathBuf, pub meta: FrontMatter, pub content: String,}
impl Page { /// Parse a content file into a `Page` structure pub fn from_file(config: &Config, src_root: &Path, path: &PathBuf) -> Result<Self> { let content = fs::read_to_string(path)?; let (frontmatter, content) = split_frontmatter(config, &content);
let options = Options::ENABLE_YAML_STYLE_METADATA_BLOCKS | Options::ENABLE_TABLES | Options::ENABLE_FOOTNOTES | Options::ENABLE_STRIKETHROUGH | Options::ENABLE_TASKLISTS; let parser = Parser::new_ext(content, options);
let mut html_output = String::new(); pulldown_cmark::html::push_html(&mut html_output, parser);
let mut rel_path = path.strip_prefix(src_root)?.to_path_buf(); rel_path.set_extension("html");
Ok(Self { path: path.to_path_buf(), rel_path, meta: frontmatter, content: html_output.to_string(), }) }}
/// Split frontmatter metadata from Markdown contentfn split_frontmatter<'a>(config: &Config, content: &'a str) -> (FrontMatter, &'a str) { let content = content.trim_start(); if content.starts_with("---") { if let Some(end) = content[3..].find("---") { let fm_str = &content[3..3 + end]; let body = &content[3 + end + 3..]; let fm: FrontMatter = serde_yaml::from_str(fm_str).unwrap_or(FrontMatter::new(config)); return (fm.merge_with_default(config), body); } } (FrontMatter::new(config), content)}