about summary refs log tree commit diff
path: root/src/atomizer.rs
blob: e6a147b6620ef1d9c7c5af8ec9fe354f8d619b2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
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("&lt;"),
			'>' => ret.push_str("&gt;"),
			'&' => ret.push_str("&amp;"),
			'\'' => ret.push_str("&apos;"),
			'"' => ret.push_str("&quot;"),
			c => ret.push(c),
		}
	}

	ret
}

fn cdataify(raw: &str) -> String {
	format!("<![CDATA[{raw}]]>")
}

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!()
			}
		}
	}
}