about summary refs log tree commit diff
path: root/src/main.rs
diff options
context:
space:
mode:
authorgennyble <gen@nyble.dev>2024-04-13 05:40:17 -0500
committergennyble <gen@nyble.dev>2024-04-13 05:40:17 -0500
commitfafb3c3ceaa16e93f69b38e33e64e240573e4875 (patch)
treec49c9eb94e6c14c089847c02ba156d5566e5b118 /src/main.rs
parent1b93aecbdc261ca2f7932db2754c6e33487dd9c8 (diff)
downloadawake-fafb3c3ceaa16e93f69b38e33e64e240573e4875.tar.gz
awake-fafb3c3ceaa16e93f69b38e33e64e240573e4875.zip
:)
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs123
1 files changed, 102 insertions, 21 deletions
diff --git a/src/main.rs b/src/main.rs
index 29716e8..b43e463 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,8 +1,11 @@
+mod atomizer;
 mod error;
 mod fs;
+mod ifc;
 mod markup;
 mod settings;
 mod templated;
+mod timeparse;
 
 use std::{os::unix::fs::MetadataExt, str::FromStr};
 
@@ -16,10 +19,12 @@ use axum::{
 };
 use bempline::{Document, Options};
 use camino::Utf8PathBuf;
+use confindent::Confindent;
 pub use error::RuntimeError;
 use fs::Filesystem;
 use settings::Settings;
 use tokio_util::io::ReaderStream;
+use tracing_subscriber::{prelude::*, EnvFilter};
 
 use crate::{
 	fs::{PathResolution, Webpath},
@@ -28,10 +33,35 @@ use crate::{
 
 #[tokio::main]
 async fn main() {
-	let fs = Filesystem::new("../inf/served");
+	match std::env::args().nth(1).as_deref() {
+		Some("atomizer") => atomizer::main(),
+		Some("serve") =>
+		/* fallthrough*/
+		{
+			()
+		}
+		_ => (),
+	}
+
+	tracing_subscriber::registry()
+		.with(tracing_subscriber::fmt::layer())
+		.with(
+			EnvFilter::try_from_default_env()
+				.or_else(|_| EnvFilter::try_new("info"))
+				.unwrap(),
+		)
+		.init();
+
+	let conf = Confindent::from_file(std::env::args().nth(2).unwrap()).unwrap();
+	let webroot: Utf8PathBuf = conf.child_parse("Webroot").unwrap();
+	let templates = conf.child_value("Templates").unwrap();
+
+	let fs = Filesystem::new(&webroot);
 
 	let settings = Settings {
-		template_dir: Utf8PathBuf::from("../inf/templates"),
+		template_dir: Utf8PathBuf::from(webroot.join(templates))
+			.canonicalize_utf8()
+			.unwrap(),
 	};
 
 	let app = Router::new()
@@ -66,30 +96,25 @@ async fn falible_handler(
 	settings: Settings,
 	path: String,
 ) -> Result<Response, RuntimeError> {
-	println!("raw = {path}");
+	tracing::debug!("webpath = {path}");
 
 	let webpath: Webpath = path.parse()?;
+	let resolve = fs.resolve(&webpath)?;
 
-	println!("path = {path}");
-
-	let PathResolution {
-		filepath,
-		is_dirfile,
-	} = fs.resolve(&webpath)?;
-
-	if !webpath.is_dir() && is_dirfile {
-		println!("as_dir = {}", webpath.as_dir());
+	if !webpath.is_dir() && resolve.is_dirfile {
 		return Ok(redirect(webpath.as_dir()));
 	}
 
-	let ext = filepath.extension().unwrap_or_default();
+	tracing::info!("serving {webpath}");
+
+	let ext = resolve.filepath.extension().unwrap_or_default();
 
 	if ext != "html" {
-		send_file(filepath).await
+		send_file(resolve.filepath).await
 	} else {
-		let content = Filesystem::read_to_string(&filepath).await?;
+		let content = Filesystem::read_to_string(&resolve.filepath).await?;
 		match Templated::from_str(&content) {
-			Ok(templated) => send_template(templated, filepath, settings).await,
+			Ok(templated) => send_template(templated, resolve, webpath, settings).await,
 			Err(_) => Ok(Response::builder()
 				.header(header::CONTENT_TYPE, "text/html")
 				.body(Body::from(content))
@@ -100,7 +125,7 @@ async fn falible_handler(
 
 fn redirect<S: Into<String>>(redirection: S) -> Response {
 	let location = redirection.into();
-	println!("redirecting to {location}");
+	tracing::info!("redirect to {location}");
 	Response::builder()
 		.status(StatusCode::TEMPORARY_REDIRECT)
 		.header(header::LOCATION, &location)
@@ -113,13 +138,16 @@ const STREAM_AFTER: u64 = 20 * 1024 * 1024;
 
 async fn send_file(filepath: Utf8PathBuf) -> Result<Response, RuntimeError> {
 	let ext = filepath.extension().unwrap_or_default();
+	let stem = filepath.file_stem().unwrap_or_default();
 
 	let mime = match ext {
 		// Text
 		"css" => "text/css",
 		"html" => "text/html",
 		"js" => "text/javascript",
-		"txt" => "txt/plain",
+		"txt" => "text/plain",
+		"xml" if stem.ends_with("atom") => "application/atom+xml",
+		"xml" => "application/xml",
 
 		// Multimedia
 		"gif" => "image/gif",
@@ -136,6 +164,8 @@ async fn send_file(filepath: Utf8PathBuf) -> Result<Response, RuntimeError> {
 
 	let metadata = Filesystem::metadata(&filepath)?;
 	if metadata.size() > STREAM_AFTER {
+		tracing::debug!("large file, streaming to client");
+
 		let file = Filesystem::open(filepath).await?;
 		let stream = ReaderStream::new(file);
 		Ok(response.body(Body::from_stream(stream)).unwrap())
@@ -147,14 +177,18 @@ async fn send_file(filepath: Utf8PathBuf) -> Result<Response, RuntimeError> {
 
 async fn send_template(
 	templated: Templated,
-	path: Utf8PathBuf,
+	resolve: PathResolution,
+	webpath: Webpath,
 	settings: Settings,
 ) -> Result<Response, RuntimeError> {
 	let template_stem = templated.frontmatter.get("template").expect("no template");
 	let template_name = Utf8PathBuf::from(format!("{template_stem}.html"));
 	let template_path = settings.template_dir.join(template_name);
 
-	let filename = path.file_name().expect("template has no filename");
+	let filename = resolve
+		.filepath
+		.file_name()
+		.expect("template has no filename");
 
 	let mut template = Document::from_file(
 		template_path,
@@ -169,6 +203,7 @@ async fn send_template(
 		templated.frontmatter.get("title").unwrap_or(filename),
 	);
 
+	// styles the templated stuff wants
 	let style_pattern = template.get_pattern("styles").unwrap();
 	for style in templated.frontmatter.get_many("style") {
 		let mut pat = style_pattern.clone();
@@ -176,7 +211,53 @@ async fn send_template(
 		template.set_pattern("styles", pat);
 	}
 
-	template.set("main", templated.content);
+	// path to the file for navigation
+	let mut path: Vec<&str> = webpath.webcanon.iter().collect();
+	// we don't want the directory/filename itself
+	path.pop();
+
+	if let Some(path_pattern) = template.get_pattern("path") {
+		let offset = match templated
+			.frontmatter
+			.get("path-offset")
+			.map(|raw| raw.parse::<usize>())
+		{
+			Some(Ok(offset)) => offset,
+			None => 0,
+			Some(Err(_)) => {
+				tracing::error!(
+					"path-offset in template {} is not an integer",
+					resolve.filepath
+				);
+
+				0
+			}
+		};
+
+		for _ in 0..offset {
+			path.pop();
+		}
+
+		let mut link = Utf8PathBuf::from("/");
+
+		let mut pat = path_pattern.clone();
+		pat.set("path_link", "/");
+		pat.set("path_name", "home");
+		template.set_pattern("path", pat);
+
+		for part in path {
+			link.push(part);
+
+			let mut pat = path_pattern.clone();
+			pat.set("path_link", &link);
+			pat.set("path_name", part);
+			template.set_pattern("path", pat);
+		}
+	}
+
+	// insert the page content itself
+	let markedup = markup::process(&templated.content);
+	template.set("main", markedup);
 
 	Ok(Response::builder()
 		.header(header::CONTENT_TYPE, "text/html")