diff --git a/todored/src/kebab.rs b/todored/src/kebab.rs new file mode 100644 index 0000000..b006d21 --- /dev/null +++ b/todored/src/kebab.rs @@ -0,0 +1,59 @@ +//! Module defining and implementing the [`Skewer`] trait. + +use regex::Regex; + + +/// Trait to skewer strings into `UPPER-KEBAB-CASE` or `lower-kebab-case`. +pub trait Skewer { + /// Replace the non-alphanumeric characters of the string with dashes. + fn to_kebab_anycase(&self) -> String; + /// Lowercase the string, then [kebabify](to_kebab_anycase) it. + fn to_kebab_lowercase(&self) -> String; + /// Uppercase the string, then [kebabify](to_kebab_anycase) it. + fn to_kebab_uppercase(&self) -> String; +} + +impl Skewer for &str { + fn to_kebab_anycase(&self) -> String { + lazy_static::lazy_static! { + static ref INVALID_CHARACTERS_REGEX: Regex = Regex::new(r#"[^A-Za-z0-9-]"#) + .expect("INVALID_CHARACTERS_REGEX to be valid"); + } + + log::trace!("Kebab-ifying: {self:?}"); + let kebab = INVALID_CHARACTERS_REGEX.replace_all(self, "-").into_owned(); + log::trace!("Kebab-ification complete: {kebab:?}"); + + kebab + } + + fn to_kebab_lowercase(&self) -> String { + log::trace!("Kebab-i-lower-fying: {self:?}"); + let kebab = self.to_ascii_lowercase().as_str().to_kebab_anycase(); + log::trace!("Kebab-i-lower-ification complete: {kebab:?}"); + + kebab + } + + fn to_kebab_uppercase(&self) -> String { + log::trace!("Kebab-i-lower-fying: {self:?}"); + let kebab = self.to_ascii_uppercase().as_str().to_kebab_anycase(); + log::trace!("Kebab-i-lower-ification complete: {kebab:?}"); + + kebab + } +} + +impl Skewer for String { + fn to_kebab_anycase(&self) -> String { + self.as_str().to_kebab_anycase() + } + + fn to_kebab_lowercase(&self) -> String { + self.as_str().to_kebab_lowercase() + } + + fn to_kebab_uppercase(&self) -> String { + self.as_str().to_kebab_uppercase() + } +} diff --git a/todored/src/main.rs b/todored/src/main.rs index 5262fcf..2e1bee5 100644 --- a/todored/src/main.rs +++ b/todored/src/main.rs @@ -6,6 +6,7 @@ pub mod outcome; pub mod task; pub(crate) mod config; mod routes; +pub mod kebab; #[tokio::main] async fn main() { diff --git a/todored/src/routes/board/axum.rs b/todored/src/routes/board/axum.rs index 52d543e..f155eb7 100644 --- a/todored/src/routes/board/axum.rs +++ b/todored/src/routes/board/axum.rs @@ -1,5 +1,6 @@ use axum::Extension; use axum::extract::{Path, WebSocketUpgrade}; +use crate::kebab::Skewer; use super::ws; pub(crate) async fn handler( @@ -7,6 +8,10 @@ pub(crate) async fn handler( Extension(rclient): Extension, upgrade_request: WebSocketUpgrade, ) -> axum::response::Response { + log::trace!("Kebabifying board name..."); + let board = board.to_kebab_lowercase(); + log::trace!("Kebabified board name to: {board:?}"); + log::trace!("Received websocket request, upgrading..."); upgrade_request.on_upgrade(|websocket| ws::handler(board, rclient, websocket)) }