Rust library to generate static websites
5
fork

Configure Feed

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

fix: dynamic pages, a bit better

+100 -35
+2
.gitignore
··· 1 1 /target 2 2 dist 3 + 4 + .DS_Store
+52
Cargo.lock
··· 139 139 checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 140 140 141 141 [[package]] 142 + name = "crossbeam-deque" 143 + version = "0.8.6" 144 + source = "registry+https://github.com/rust-lang/crates.io-index" 145 + checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" 146 + dependencies = [ 147 + "crossbeam-epoch", 148 + "crossbeam-utils", 149 + ] 150 + 151 + [[package]] 152 + name = "crossbeam-epoch" 153 + version = "0.9.18" 154 + source = "registry+https://github.com/rust-lang/crates.io-index" 155 + checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 156 + dependencies = [ 157 + "crossbeam-utils", 158 + ] 159 + 160 + [[package]] 161 + name = "crossbeam-utils" 162 + version = "0.8.21" 163 + source = "registry+https://github.com/rust-lang/crates.io-index" 164 + checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 165 + 166 + [[package]] 167 + name = "either" 168 + version = "1.13.0" 169 + source = "registry+https://github.com/rust-lang/crates.io-index" 170 + checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 171 + 172 + [[package]] 142 173 name = "env_filter" 143 174 version = "0.1.2" 144 175 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 262 293 "log", 263 294 "maud", 264 295 "maudit-macros", 296 + "rayon", 265 297 ] 266 298 267 299 [[package]] ··· 340 372 checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" 341 373 dependencies = [ 342 374 "proc-macro2", 375 + ] 376 + 377 + [[package]] 378 + name = "rayon" 379 + version = "1.10.0" 380 + source = "registry+https://github.com/rust-lang/crates.io-index" 381 + checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" 382 + dependencies = [ 383 + "either", 384 + "rayon-core", 385 + ] 386 + 387 + [[package]] 388 + name = "rayon-core" 389 + version = "1.12.1" 390 + source = "registry+https://github.com/rust-lang/crates.io-index" 391 + checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" 392 + dependencies = [ 393 + "crossbeam-deque", 394 + "crossbeam-utils", 343 395 ] 344 396 345 397 [[package]]
+1
crates/framework/Cargo.toml
··· 12 12 env_logger = "0.11.5" 13 13 chrono = "0.4.39" 14 14 colored = "2.2.0" 15 + rayon = "1.10.0"
+28 -16
crates/framework/src/lib.rs
··· 15 15 16 16 use colored::{ColoredString, Colorize}; 17 17 use env_logger::{Builder, Env}; 18 + 18 19 use logging::{format_elapsed_time, FormatElapsedTimeOptions}; 20 + 19 21 pub use maud; 20 22 pub use maudit_macros; 21 23 ··· 23 25 use page::RouteContext; 24 26 25 27 pub fn coronate(router: routes::Router) -> Result<(), Box<dyn std::error::Error>> { 28 + let build_start = SystemTime::now(); 26 29 let logging_env = Env::default().filter_or("RUST_LOG", "info"); 27 30 Builder::from_env(logging_env) 28 31 .format(|buf, record| { ··· 53 56 let pages_start = SystemTime::now(); 54 57 55 58 for route in &router.routes { 56 - let route_start = SystemTime::now(); 57 - 58 - match route.routes().is_empty() { 59 + let routes = route.routes(); 60 + match routes.is_empty() { 59 61 true => { 62 + let route_start = SystemTime::now(); 60 63 let ctx = RouteContext { 61 64 params: HashMap::new(), 62 65 }; ··· 100 103 } 101 104 false => { 102 105 info!(target: "build", "{}", route.route_raw().to_string().bold()); 103 - for (index, (params_key, params_value)) in route.routes().into_iter().enumerate() { 104 - let ctx = RouteContext { 105 - params: vec![(params_key, params_value)].into_iter().collect(), 106 - }; 106 + 107 + routes.into_iter().for_each(|params| { 108 + let route_start = SystemTime::now(); 109 + let ctx = RouteContext { params }; 107 110 108 111 let file_path = PathBuf::from_str("./dist/") 109 112 .unwrap() ··· 111 114 112 115 // Create the parent directories if it doesn't exist 113 116 let parent_dir = Path::new(file_path.parent().unwrap()); 114 - fs::create_dir_all(parent_dir)?; 117 + fs::create_dir_all(parent_dir).unwrap(); 115 118 116 119 // Create file 117 120 let mut file = File::create(file_path.clone()).unwrap(); ··· 139 142 })), 140 143 ..Default::default() 141 144 }, 142 - )?; 143 - let ascii_sign = if index < route.routes().len() - 1 { 144 - "├─" 145 - } else { 146 - "└─" 147 - }; 148 - info!(target: "build", "{} {} {}", ascii_sign, file_path.to_string_lossy().dimmed(), formatted_elasped_time); 149 - } 145 + ).unwrap(); 146 + info!(target: "build", "├─ {} {}", file_path.to_string_lossy().dimmed(), formatted_elasped_time); 147 + }); 150 148 } 151 149 } 152 150 } ··· 156 154 FormatElapsedTimeOptions { 157 155 sec_red_threshold: 5, 158 156 sec_yellow_threshold: 1, 157 + millis_red_threshold: None, 158 + millis_yellow_threshold: None, 159 159 ..Default::default() 160 160 }, 161 161 )?; ··· 173 173 format_elapsed_time(assets_start.elapsed(), FormatElapsedTimeOptions::default())?; 174 174 info!(target: "build", "{}", format!("Assets copied in {}", formatted_elasped_time).bold()); 175 175 } 176 + 177 + let formatted_elasped_time = format_elapsed_time( 178 + build_start.elapsed(), 179 + FormatElapsedTimeOptions { 180 + sec_red_threshold: 5, 181 + sec_yellow_threshold: 1, 182 + millis_red_threshold: None, 183 + millis_yellow_threshold: None, 184 + ..Default::default() 185 + }, 186 + )?; 187 + info!(target: "build", "{}", format!("Build completed in {}", formatted_elasped_time).bold()); 176 188 177 189 Ok(()) 178 190 }
+2 -2
crates/framework/src/page.rs
··· 14 14 } 15 15 16 16 pub trait DynamicPage { 17 - fn routes(&self) -> HashMap<String, String>; 17 + fn routes(&self) -> Vec<HashMap<String, String>>; 18 18 } 19 19 20 20 pub trait InternalPage { ··· 23 23 fn file_path(&self, params: HashMap<String, String>) -> PathBuf; 24 24 } 25 25 26 - pub trait FullPage: Page + InternalPage + DynamicPage {} 26 + pub trait FullPage: Page + InternalPage + DynamicPage + Sync {}
+5 -6
crates/macros/src/lib.rs
··· 40 40 false => quote! {}, 41 41 true => quote! { 42 42 impl DynamicPage for #struct_name { 43 - fn routes(&self) -> std::collections::HashMap<String, String> { 44 - let mut routes = std::collections::HashMap::new(); 45 - routes 43 + fn routes(&self) -> Vec<std::collections::HashMap<String, String>> { 44 + Vec::new() 46 45 } 47 46 } 48 47 }, ··· 135 134 values 136 135 } 137 136 138 - fn url_to_file_path(url: &str, is_file: bool, params: &Vec<Parameter>) -> String { 137 + fn url_to_file_path(url: &str, is_file: bool, params: &[Parameter]) -> String { 139 138 let file_path = match is_file { 140 139 false => { 141 140 // Remove the leading '/' from the URL if it exists ··· 161 160 } 162 161 }; 163 162 164 - make_params_dynamic(&file_path, &params, 1) 163 + make_params_dynamic(&file_path, params, 1) 165 164 } 166 165 167 - fn make_params_dynamic(file_path: &str, params: &Vec<Parameter>, offset: usize) -> String { 166 + fn make_params_dynamic(file_path: &str, params: &[Parameter], offset: usize) -> String { 168 167 let mut file_path = file_path.to_string(); 169 168 for param in params.iter().rev() { 170 169 file_path.replace_range(
+10 -11
crates/user-example/src/pages/index.rs
··· 1 - use maudit::assets::Asset; 2 1 use maudit::maud::html; 3 2 use maudit::maudit_macros::route; 4 3 use maudit::page::RouteContext; ··· 8 7 9 8 impl Page for Index { 10 9 fn render(&self, ctx: &RouteContext) -> RenderResult { 11 - let social_card = Asset::new("./data/social-card.png".into()); 12 - 13 10 let params = ctx.params.get("page").unwrap(); 14 11 15 12 RenderResult::Html(html! { 16 13 h1 { "Hello, world!" } 17 - img src=(social_card) alt="Social card"; 18 - p { (params) } 14 + p { (params) } 19 15 }) 20 16 } 21 17 } 22 18 23 19 impl DynamicPage for Index { 24 - fn routes(&self) -> std::collections::HashMap<String, String> { 25 - let mut routes = std::collections::HashMap::new(); 26 - for i in 1..=100 { 27 - routes.insert("page".to_string(), format!("Hello {}", i)); 28 - } 29 - routes 20 + fn routes(&self) -> Vec<std::collections::HashMap<String, String>> { 21 + // Return 100 routes 22 + (0..1000) 23 + .map(|i| { 24 + let mut map = std::collections::HashMap::new(); 25 + map.insert("page".into(), i.to_string()); 26 + map 27 + }) 28 + .collect() 30 29 } 31 30 }