Rust library to generate static websites
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: check urls at runtime

+43 -3
+1
Cargo.lock
··· 1117 1117 "rayon", 1118 1118 "rolldown", 1119 1119 "rustc-hash", 1120 + "thiserror 2.0.9", 1120 1121 "tokio", 1121 1122 ] 1122 1123
+1
crates/framework/Cargo.toml
··· 17 17 dyn-eq = "0.1.3" 18 18 rolldown = { git = "https://github.com/rolldown/rolldown", version = "0.1.0", rev = "f9fc700f00b9a4ef3659c70d2be4d7cd61b492c8" } 19 19 tokio = { version = "1", features = ["macros", "rt-multi-thread"] } 20 + thiserror = "2.0.9"
+12 -1
crates/framework/src/page.rs
··· 45 45 fn route_raw(&self) -> String; 46 46 fn route(&self, params: &RouteParams) -> String; 47 47 fn file_path(&self, params: &RouteParams) -> PathBuf; 48 - fn url<P: Into<RouteParams>>(params: P) -> String 48 + fn url_unsafe<P: Into<RouteParams>>(params: P) -> String 49 + where 50 + Self: Sized; 51 + fn url<P: Into<RouteParams>>(&self, params: P) -> Result<String, UrlError> 49 52 where 50 53 Self: Sized; 54 + } 55 + 56 + use thiserror::Error; 57 + 58 + #[derive(Error, Debug)] 59 + pub enum UrlError { 60 + #[error("Route not found")] 61 + RouteNotFound, 51 62 } 52 63 53 64 pub trait FullPage: Page + InternalPage + DynamicPage + Sync {}
+23 -1
crates/macros/src/lib.rs
··· 148 148 std::path::PathBuf::from(format!(#file_path_for_route)) 149 149 } 150 150 151 - fn url<P: Into<maudit::page::RouteParams>>(params: P) -> String { 151 + fn url_unsafe<P: Into<maudit::page::RouteParams>>(params: P) -> String { 152 152 let params = params.into(); 153 153 #(#list_params;)* 154 154 format!(#path_for_route) 155 + } 156 + 157 + fn url<P: Into<maudit::page::RouteParams>>(&self, params: P) -> Result<String, maudit::page::UrlError> { 158 + let params = params.into(); 159 + 160 + // Check that the params refer to a page that exists 161 + let all_routes = self::DynamicPage::routes(self); 162 + let mut found = false; 163 + 164 + for route in all_routes { 165 + if (route.0 == params.0) { 166 + found = true; 167 + break; 168 + } 169 + } 170 + 171 + if !found { 172 + return Err(maudit::page::UrlError::RouteNotFound); 173 + } 174 + 175 + #(#list_params;)* 176 + Ok(format!(#path_for_route)) 155 177 } 156 178 } 157 179
+6 -1
crates/user-example/src/pages/index.rs
··· 12 12 let image = ctx.assets.add_image("data/logo.svg".into()); 13 13 let script = ctx.assets.add_script("data/some_other_script.js".into()); 14 14 15 - let link_to_first_dynamic = DynamicExample::url(&DynamicExampleParams { page: 1 }); 15 + let link_to_first_dynamic = DynamicExample::url_unsafe(&DynamicExampleParams { page: 1 }); 16 + 17 + let safe_link_to_first_dynamic = DynamicExample 18 + .url(&DynamicExampleParams { page: 2 }) 19 + .unwrap(); 16 20 17 21 RenderResult::Html(html! { 18 22 h1 { "Index" } 19 23 img src=(image.path.to_string_lossy()) {} 20 24 script src=(script.path.to_string_lossy()) {} 21 25 a href=(link_to_first_dynamic) { "Go to first dynamic page" } 26 + a href=(safe_link_to_first_dynamic) { "Go to first dynamic page (safe)" } 22 27 }) 23 28 } 24 29 }