From 1b93aecbdc261ca2f7932db2754c6e33487dd9c8 Mon Sep 17 00:00:00 2001 From: gennyble Date: Sat, 13 Apr 2024 05:39:43 -0500 Subject: Atomizer: generate atom feeds --- src/atomizer.rs | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 src/atomizer.rs (limited to 'src/atomizer.rs') diff --git a/src/atomizer.rs b/src/atomizer.rs new file mode 100644 index 0000000..e6a147b --- /dev/null +++ b/src/atomizer.rs @@ -0,0 +1,163 @@ +use std::str::FromStr; + +use bempline::{variables, Document, Options}; +use camino::{Utf8Path, Utf8PathBuf}; +use confindent::{Confindent, Value}; +use cutie::Html; +use time::format_description::well_known; + +use crate::{markup, templated::Templated, timeparse}; + +pub fn main() -> ! { + let awake_conf = Confindent::from_file(std::env::args().nth(2).unwrap()).unwrap(); + let atom_conf_path = std::env::args().nth(3).unwrap_or(String::from("atom.conf")); + + let atom_conf = Confindent::from_file(atom_conf_path).unwrap(); + + let root: Utf8PathBuf = awake_conf.child_parse("Webroot").unwrap(); + let atom = Document::from_file( + root.clone() + .join(atom_conf.child_value("Template").unwrap()) + .canonicalize_utf8() + .unwrap(), + Options::default(), + ) + .unwrap(); + + let feeds = atom_conf.children("Feed"); + for feed in feeds { + make_feed(feed, &root, atom.clone()) + } + + std::process::exit(0); +} + +pub fn make_feed(feed: &Value, root: &Utf8Path, mut atom: Document) { + let feed_relout: Utf8PathBuf = feed.child_parse("Output").unwrap(); + let feed_link = feed.child_owned("Link").unwrap(); + let feed_id = feed.child_owned("Id").unwrap(); + let feed_title = feed.child_owned("Title").unwrap(); + let feed_subtitle = feed.child_owned("Subtitle").unwrap(); + let feed_updated = feed.child_owned("Updated").unwrap(); + let feed_author_name = feed.get("Author/Name").unwrap(); + let feed_author_email = feed.get("Author/Email").unwrap(); + + variables!( + atom, + feed_link, + feed_id, + feed_title, + feed_subtitle, + feed_updated, + feed_author_email, + feed_author_name + ); + + let entries = feed.children("Entry"); + let entry_pattern = atom.get_pattern("entry").unwrap(); + for entry in entries { + let entry_relpath: Utf8PathBuf = entry.parse().unwrap(); + let entry_path = root.join(&entry_relpath); + + println!("entry {entry_relpath}"); + + let entry_content = match std::fs::read_to_string(&entry_path) { + Ok(ok) => ok, + Err(e) => { + panic!("failed to get file at {entry_path}: {e}"); + } + }; + let entry_templated = Templated::from_str(&entry_content).unwrap(); + + let entry_title = entry + .child_value("Title") + .unwrap_or_else(|| entry_templated.frontmatter.get("title").unwrap()); + let entry_link = entry.child_value("Link").unwrap(); + let entry_id = entry.child_value("Id").unwrap(); + + let entry_published_raw = entry + .child_value("Published") + .unwrap_or_else(|| entry_templated.frontmatter.get("published").unwrap()); + + let entry_updated = timeparse::parse(entry.child_value("Updated").unwrap_or_else(|| { + entry_templated + .frontmatter + .get("updated") + .unwrap_or(entry_published_raw) + })) + .unwrap() + .format(&well_known::Rfc3339) + .unwrap(); + + let entry_published = timeparse::parse(entry_published_raw) + .unwrap() + .format(&well_known::Rfc3339) + .unwrap(); + + let mut entry_content = markup::process(&entry_templated.content); + + if let Some(part_id) = entry + .child_value("Part") + .map(|raw| raw.strip_prefix('#')) + .flatten() + { + let cutie = cutie::Html::parse(entry_content); + let found = cutie.get_by_id(part_id).unwrap(); + entry_content = found.to_string(); + } + + let mut pattern = entry_pattern.clone(); + variables!( + pattern, + entry_title, + entry_link, + entry_id, + entry_published, + entry_updated + ); + pattern.set("entry_content", cdataify(&entry_content)); + atom.set_pattern("entry", pattern); + } + + let string = atom.compile(); + + let feed_out = root.join(feed_relout); + std::fs::write(feed_out, string).unwrap(); +} + +//FIXME: do NOT use this name +fn htmlspecialchars(raw: &str) -> String { + let mut ret = String::new(); + + for ch in raw.chars() { + match ch { + '<' => ret.push_str("<"), + '>' => ret.push_str(">"), + '&' => ret.push_str("&"), + '\'' => ret.push_str("'"), + '"' => ret.push_str("""), + c => ret.push(c), + } + } + + ret +} + +fn cdataify(raw: &str) -> String { + format!("") +} + +fn fix_links(html: &mut Html, path: Utf8PathBuf) { + let root = match path.file_name() { + Some(_) => path.parent().unwrap().to_owned(), + None => path, + }; + + for tag in html.child_tags_mut() { + if let Some(src) = tag.get_attribute("src") { + if !src.starts_with("http") { + todo!() + } + } + } +} -- cgit 1.4.1-3-g733a5