diff options
author | metamuffin <metamuffin@disroot.org> | 2022-08-29 22:53:37 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2022-08-29 22:53:37 +0200 |
commit | 3eb1adfeb8dd477479404a1269c8682e3b4edf12 (patch) | |
tree | 1a4788149dc4b958dee129c28b95553cc3927f16 /code/src/main.rs | |
parent | a4dd9c4944340505962f07853d53ab02f3a02336 (diff) | |
download | metamuffin-blog-3eb1adfeb8dd477479404a1269c8682e3b4edf12.tar metamuffin-blog-3eb1adfeb8dd477479404a1269c8682e3b4edf12.tar.bz2 metamuffin-blog-3eb1adfeb8dd477479404a1269c8682e3b4edf12.tar.zst |
split files
Diffstat (limited to 'code/src/main.rs')
-rw-r--r-- | code/src/main.rs | 179 |
1 files changed, 50 insertions, 129 deletions
diff --git a/code/src/main.rs b/code/src/main.rs index d90139e..ed0a62a 100644 --- a/code/src/main.rs +++ b/code/src/main.rs @@ -1,15 +1,23 @@ +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::{read_to_string, File}, + fs::File, io::{BufRead, BufReader, Write}, path::PathBuf, }; -use clap::{Parser, Subcommand}; -use laby::{html, internal::Buffer, iter, li, raw, ul, Render}; -use markdown::{Block, ListItem, Span}; +pub const BLOG_BASE: &'static str = "s.metamuffin.org/temp/blog-preview"; #[derive(Parser)] -struct Args { +pub struct Args { + #[clap(short, long)] + root: Option<String>, #[clap(short, long)] output: Option<String>, #[clap(subcommand)] @@ -17,29 +25,33 @@ struct Args { } #[derive(Subcommand)] -enum ArgAction { +pub enum ArgAction { RenderArticle { input: String }, - RenderIndex { root: String }, + RenderIndex, + GenerateAtom, } fn main() { let args = Args::parse(); - match args.action { + match &args.action { ArgAction::RenderArticle { input } => { let mut out = Buffer::new(); - article(input).render(&mut out); - write_output(&args.output, out.into_string()); + article(input.to_owned()).render(&mut out); + write_output(&args, out.into_string()); } - ArgAction::RenderIndex { root } => { + ArgAction::RenderIndex => { let mut out = Buffer::new(); - index(root).render(&mut out); - write_output(&args.output, out.into_string()); + 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: &Option<String>, o: String) { - if let Some(f) = t { +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 { @@ -47,125 +59,34 @@ fn write_output(t: &Option<String>, o: String) { } } -fn scaffold(title: String, body: impl Render) -> impl Render { - html!( - head!( - link!(rel = "stylesheet", href = "./style.css"), - title!(format!("{} - metamuffin's blog", title)) - ), - body!( - nav!(h2!("metamuffin's blog"), a!(href = "./index.html", "index")), - article!(body), - footer!(p!("written by metamuffin, licensed under CC-BY-ND-4.0")) - ) - ) +pub fn get_articles(root: &str) -> Vec<ArticleMeta> { + let mut a = std::fs::read_dir(root) + .unwrap() + .map(|e| e.unwrap()) + .map(|e| article_metadata(e.path())) + .collect::<Vec<_>>(); + 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 } -fn index(root: String) -> impl Render { - scaffold( - "index".to_string(), - ul!(iter!(std::fs::read_dir(root) - .unwrap() - .map(|e| e.unwrap()) - .map(|e| ( - e.file_name().to_str().unwrap().to_string(), - article_title(e.path()) - )) - .map(|(path, title)| li!( - path.as_str()[0..10].to_string(), - ": ", - a!(href = format!("./{}", path.replace(".md", ".html")), title) - )))), - ) +pub struct ArticleMeta { + title: String, + filename: String, + date: iso8601::Date, + path: PathBuf, } - -fn article_title(path: PathBuf) -> String { - let f = File::open(path).unwrap(); +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 - String::from(&buf[2..]) -} - -fn article(path: String) -> impl Render { - scaffold( - article_title(path.clone().into()), - raw!(blocks_to_html(markdown::tokenize( - &read_to_string(path).unwrap() - ))), - ) -} - -fn span_to_html(ss: Vec<Span>) -> String { - let mut out = String::new(); - for s in ss { - out += match s { - Span::Break => format!("<br/>"), - Span::Text(t) => escape(&t), - Span::Code(c) => format!("<code>{}</code>", escape(&c)), - Span::Link(text, url, _) => { - format!("<a href=\"{}\">{}</a>", escape(&url), escape(&text)) - } - Span::Image(_, _, _) => todo!(), - Span::Emphasis(c) => format!("<i>{}</i>", span_to_html(c)), - Span::Strong(c) => format!("<b>{}</b>", span_to_html(c)), - } - .as_str() - } - out -} -fn blocks_to_html(blocks: Vec<Block>) -> String { - let mut out = String::new(); - for e in blocks { - out += match e { - Block::Header(text, level) => { - format!("<h{level}>{}</h{level}>", span_to_html(text)) - } - Block::Paragraph(p) => format!("<p>{}</p>", span_to_html(p)), - Block::Blockquote(q) => format!("<quote>{}</quote>", blocks_to_html(q)), - Block::CodeBlock(_syntax, content) => { - format!("<code><pre>{}</pre></code>", escape(&content)) // TODO syntax highlighting - } - Block::OrderedList(els, _) => format!( - "<ol>{}</ol>", - els.into_iter() - .map(|e| format!( - "<li>{}</li>", - match e { - ListItem::Simple(s) => span_to_html(s), - ListItem::Paragraph(b) => blocks_to_html(b), - } - )) - .collect::<Vec<_>>() - .join("") - ), - Block::UnorderedList(els) => { - format!( - "<ul>{}</ul>", - els.into_iter() - .map(|e| format!( - "<li>{}</li>", - match e { - ListItem::Simple(s) => span_to_html(s), - ListItem::Paragraph(b) => blocks_to_html(b), - } - )) - .collect::<Vec<_>>() - .join("") - ) - } - Block::Raw(r) => r, - Block::Hr => format!("<hr/>"), - } - .as_str(); + ArticleMeta { + title: String::from(&buf[2..]), + filename: path.file_name().unwrap().to_str().unwrap().to_string(), + date: iso8601::date(&path.file_name().unwrap().to_str().unwrap()[0..10]).unwrap(), + path, } - out -} - -fn escape(text: &str) -> String { - text.replace("&", "&") - .replace("<", "<") - .replace(">", ">") - .replace("'", "’") - .replace("\"", """) } |