pub mod atom; pub mod html; pub mod markdown; use atom::generate_atom; use clap::{Parser, Subcommand}; use html::{article, index}; use laby::{internal::Buffer, Render}; use std::{ fs::File, io::{BufRead, BufReader, Write}, path::PathBuf, }; pub const BLOG_BASE: &'static str = "s.metamuffin.org/temp/blog-preview"; #[derive(Parser)] pub struct Args { #[clap(short, long)] root: Option, #[clap(short, long)] output: Option, #[clap(subcommand)] action: ArgAction, } #[derive(Subcommand)] pub enum ArgAction { RenderArticle { input: String }, RenderIndex, GenerateAtom, } fn main() { let args = Args::parse(); match &args.action { ArgAction::RenderArticle { input } => { let mut out = Buffer::new(); article(input.to_owned()).render(&mut out); write_output(&args, out.into_string()); } ArgAction::RenderIndex => { let mut out = Buffer::new(); index(&args.root.as_ref().unwrap()).render(&mut out); write_output(&args, out.into_string()); } ArgAction::GenerateAtom => { write_output(&args, generate_atom(&args)); } } } fn write_output(t: &Args, o: String) { if let Some(f) = &t.output { let mut f = File::create(f).unwrap(); f.write_fmt(format_args!("{o}")).unwrap() } else { println!("{o}") } } pub fn get_articles(root: &str) -> Vec { let mut a = std::fs::read_dir(root) .unwrap() .map(|e| e.unwrap()) .map(|e| article_metadata(e.path())) .collect::>(); a.sort_by_cached_key(|e| -match e.date { iso8601::Date::YMD { year, month, day } => day as i32 + month as i32 * 40 + year * 37, _ => unreachable!(), }); a } pub struct ArticleMeta { title: String, filename: String, date: iso8601::Date, path: PathBuf, } fn article_metadata(path: PathBuf) -> ArticleMeta { let f = File::open(&path).unwrap(); let mut f = BufReader::new(f); let mut buf = String::new(); f.read_line(&mut buf).unwrap(); // assume the 1st line has the title ArticleMeta { title: String::from(buf[2..].trim()), filename: path.file_name().unwrap().to_str().unwrap().to_string(), date: iso8601::date(&path.file_name().unwrap().to_str().unwrap()[0..10]).unwrap(), path, } }