diff --git a/src/formats.rs b/src/formats.rs index 6620fec..043f98d 100644 --- a/src/formats.rs +++ b/src/formats.rs @@ -18,10 +18,22 @@ pub fn populate_graph() -> Graph { Graph { nodes: nodes.clone(), incoming: make_incoming(&nodes), + lowercase_keymap: map_lowercase_keys(&nodes), ..graph } } +fn map_lowercase_keys( + source_map: &HashMap, +) -> HashMap { + let mut out_map: HashMap = HashMap::new(); + let keys = source_map.keys(); + for key in keys { + out_map.insert(key.clone().to_lowercase(), key.clone()); + } + out_map +} + fn modulate_nodes(old_nodes: &HashMap) -> HashMap { let mut nodes: HashMap = HashMap::new(); diff --git a/src/handlers/graph.rs b/src/handlers/graph.rs index 321a43e..676c761 100644 --- a/src/handlers/graph.rs +++ b/src/handlers/graph.rs @@ -1,4 +1,6 @@ -use axum::{body::Body, extract::Path, http::Response}; +use axum::response::IntoResponse as _; +use axum::{body::Body, extract::Path, http::Response, response::Redirect}; + use crate::syntax::content; use crate::{formats::populate_graph, handlers, types::Node}; @@ -6,7 +8,12 @@ use crate::{formats::populate_graph, handlers, types::Node}; pub async fn node(Path(id): Path) -> Response { let graph = populate_graph(); let empty_node = Node::new(Some(format!("Could not find node ID {id}."))); - let node: &Node = graph.nodes.get(&id).unwrap_or(&empty_node); + let node = graph.find_node(&id).unwrap_or(empty_node.clone()); + + if !graph.nodes.contains_key(&id) { + return Redirect::permanent(format!("/node/{}", node.id).as_str()) + .into_response(); + } let mut context = tera::Context::new(); context.insert("node", &node); @@ -14,11 +21,10 @@ pub async fn node(Path(id): Path) -> Response { context.insert("incoming", &graph.incoming.get(&id)); context.insert("config", &graph.meta.config.parse_text()); - let not_found = *node == empty_node; - let template_name = "node.html".to_string(); + let not_found = node == empty_node; handlers::template::by_filename( - &template_name, + "node.html", &context, if not_found { 404 } else { 500 }, Some( diff --git a/src/types.rs b/src/types.rs index ba099f7..dfb5c38 100644 --- a/src/types.rs +++ b/src/types.rs @@ -10,6 +10,8 @@ pub struct Graph { pub root_node: String, #[serde(skip_deserializing)] pub incoming: HashMap>, + #[serde(skip_deserializing)] + pub lowercase_keymap: HashMap, #[serde(default)] pub meta: Meta, } @@ -113,6 +115,7 @@ impl Graph { nodes: HashMap::new(), root_node: "VoidNode".to_string(), incoming: HashMap::new(), + lowercase_keymap: HashMap::new(), meta: Meta { config: Config { site_title: String::new(), @@ -140,6 +143,15 @@ impl Graph { } } + pub fn find_node(&self, query: &str) -> Option { + self.nodes.get(query).cloned().or_else(|| { + self.lowercase_keymap + .get(query) + .and_then(|lower_key| self.nodes.get(lower_key)) + .cloned() + }) + } + pub fn get_root(&self) -> Option { self.nodes.get(&self.root_node).cloned() }