aboutsummaryrefslogtreecommitdiff
path: root/code/src/main.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2022-08-29 22:53:37 +0200
committermetamuffin <metamuffin@disroot.org>2022-08-29 22:53:37 +0200
commit3eb1adfeb8dd477479404a1269c8682e3b4edf12 (patch)
tree1a4788149dc4b958dee129c28b95553cc3927f16 /code/src/main.rs
parenta4dd9c4944340505962f07853d53ab02f3a02336 (diff)
downloadmetamuffin-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.rs179
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("&", "&amp;")
- .replace("<", "&lt;")
- .replace(">", "&gt;")
- .replace("'", "&#8217;")
- .replace("\"", "&quot;")
}