Rust library to generate static websites
5
fork

Configure Feed

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

feat: don't make user depend on tokio

+84 -40
+1 -1
Cargo.lock
··· 1117 1117 "rayon", 1118 1118 "rolldown", 1119 1119 "rustc-hash", 1120 + "tokio", 1120 1121 ] 1121 1122 1122 1123 [[package]] ··· 1125 1126 dependencies = [ 1126 1127 "maud", 1127 1128 "maudit", 1128 - "tokio", 1129 1129 ] 1130 1130 1131 1131 [[package]]
+1
crates/framework/Cargo.toml
··· 16 16 rustc-hash = "2.1" 17 17 dyn-eq = "0.1.3" 18 18 rolldown = { git = "https://github.com/rolldown/rolldown", version = "0.1.0", rev = "f9fc700f00b9a4ef3659c70d2be4d7cd61b492c8" } 19 + tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
+24 -10
crates/framework/src/lib.rs
··· 2 2 mod assets; 3 3 pub mod page; 4 4 pub mod params; 5 - mod routes; 6 - 7 - pub use routes::Router; 8 5 9 6 // Re-exported dependencies for user convenience 10 7 pub use rustc_hash::FxHashMap; 8 + 9 + pub use maudit_macros::generate_pages_mod; 11 10 12 11 // Internal modules 13 12 mod logging; ··· 23 22 use colored::{ColoredString, Colorize}; 24 23 use env_logger::{Builder, Env}; 25 24 use log::{info, trace}; 26 - use page::{RouteContext, RouteParams}; 25 + use page::{FullPage, RouteContext, RouteParams}; 27 26 use rolldown::{Bundler, BundlerOptions, InputItem}; 28 27 use rustc_hash::FxHashSet; 29 28 30 29 use assets::Asset; 31 30 use logging::{format_elapsed_time, FormatElapsedTimeOptions}; 32 31 33 - pub async fn coronate(router: routes::Router<'_>) -> Result<(), Box<dyn std::error::Error>> { 32 + #[macro_export] 33 + macro_rules! routes { 34 + [$($route:ident),*] => { 35 + vec![$(&$route),*] 36 + }; 37 + } 38 + 39 + pub fn coronate(routes: Vec<&dyn FullPage>) -> Result<(), Box<dyn std::error::Error>> { 40 + tokio::runtime::Builder::new_multi_thread() 41 + .enable_all() 42 + .build() 43 + .unwrap() 44 + .block_on(async { build(routes).await }) 45 + } 46 + 47 + pub async fn build(routes: Vec<&dyn FullPage>) -> Result<(), Box<dyn std::error::Error>> { 34 48 let build_start = SystemTime::now(); 35 49 let logging_env = Env::default().filter_or("RUST_LOG", "info"); 36 50 Builder::from_env(logging_env) ··· 84 98 let mut build_pages_assets: FxHashSet<Box<dyn Asset>> = FxHashSet::default(); 85 99 let mut build_pages_scripts: FxHashSet<assets::Script> = FxHashSet::default(); 86 100 87 - for route in &router.routes { 101 + for route in routes { 88 102 let routes = route.routes(); 89 103 match routes.is_empty() { 90 104 true => { ··· 95 109 assets: &mut page_assets, 96 110 }; 97 111 98 - let (file_path, file) = create_route_file(&**route, &ctx.params)?; 99 - render_route(file, &**route, &mut ctx)?; 112 + let (file_path, file) = create_route_file(route, &ctx.params)?; 113 + render_route(file, route, &mut ctx)?; 100 114 101 115 let formatted_elasped_time = 102 116 format_elapsed_time(route_start.elapsed(), &route_format_options)?; ··· 115 129 let route_start = SystemTime::now(); 116 130 let mut ctx = RouteContext { params, assets: &mut pages_assets }; 117 131 118 - let (file_path, file) = create_route_file(&**route, &ctx.params).unwrap(); 119 - render_route(file, &**route, &mut ctx).unwrap(); 132 + let (file_path, file) = create_route_file(route, &ctx.params).unwrap(); 133 + render_route(file, route, &mut ctx).unwrap(); 120 134 121 135 let formatted_elasped_time = format_elapsed_time(route_start.elapsed(), &route_format_options).unwrap(); 122 136 info!(target: "build", "├─ {} {}", file_path.to_string_lossy().dimmed(), formatted_elasped_time);
-11
crates/framework/src/routes.rs
··· 1 - use crate::page::FullPage; 2 - 3 - pub struct Router<'a> { 4 - pub(crate) routes: Vec<&'a dyn FullPage>, 5 - } 6 - 7 - impl<'a> Router<'a> { 8 - pub fn new(routes: Vec<&'a dyn FullPage>) -> Router<'a> { 9 - Router { routes } 10 - } 11 - }
+54
crates/macros/src/lib.rs
··· 26 26 } 27 27 } 28 28 29 + struct GeneratePagesModAttributes { 30 + directory: Option<String>, 31 + } 32 + 33 + impl Parse for GeneratePagesModAttributes { 34 + fn parse(input: ParseStream) -> Result<Self> { 35 + let directory = input.parse::<Option<LitStr>>()?; 36 + 37 + Ok(GeneratePagesModAttributes { 38 + directory: directory.map(|d| d.value()), 39 + }) 40 + } 41 + } 42 + 43 + #[proc_macro] 44 + pub fn generate_pages_mod(item: TokenStream) -> TokenStream { 45 + // Add support for passing a directory to generate the pages mod 46 + let attributes: GeneratePagesModAttributes = syn::parse_macro_input!(item); 47 + 48 + let directory = attributes.directory.unwrap_or("pages".to_string()); 49 + 50 + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); 51 + let directory_files = std::fs::read_dir(format!( 52 + "{}/src/{}", 53 + manifest_dir, 54 + directory.trim_start_matches('/') 55 + )) 56 + .unwrap(); 57 + 58 + let mut page_mods = Vec::new(); 59 + 60 + for file in directory_files { 61 + let file = file.unwrap(); 62 + let file_name = file.file_name(); 63 + let file_name = file_name.to_str().unwrap(); 64 + let file_name = file_name.trim_end_matches(".rs"); 65 + 66 + page_mods.push(format_ident!("{}", file_name)); 67 + } 68 + 69 + let expanded = quote! { 70 + mod pages { 71 + #( 72 + mod #page_mods; 73 + pub use #page_mods::*; 74 + )* 75 + } 76 + 77 + pub use pages::*; 78 + }; 79 + 80 + TokenStream::from(expanded) 81 + } 82 + 29 83 #[proc_macro_attribute] 30 84 pub fn route(attrs: TokenStream, item: TokenStream) -> TokenStream { 31 85 // Parse the input tokens into a syntax tree
-1
crates/user-example/Cargo.toml
··· 7 7 [dependencies] 8 8 maudit = { path = "../framework" } 9 9 maud = "0.26.0" 10 - tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
+4 -10
crates/user-example/src/main.rs
··· 1 - mod pages; 2 - use maudit::Router; 1 + use maudit::{coronate, generate_pages_mod, routes}; 3 2 4 - #[tokio::main] 5 - async fn main() -> Result<(), Box<dyn std::error::Error>> { 6 - let router = Router::new(vec![ 7 - &pages::DynamicExample, 8 - &pages::Endpoint, 9 - &pages::Index, 10 - ]); 3 + generate_pages_mod!(); 11 4 12 - maudit::coronate(router).await 5 + fn main() -> Result<(), Box<dyn std::error::Error>> { 6 + coronate(routes![Index, DynamicExample, Endpoint]) 13 7 }
-7
crates/user-example/src/pages.rs
··· 1 - mod dynamic; 2 - mod endpoint; 3 - mod index; 4 - 5 - pub use dynamic::DynamicExample; 6 - pub use endpoint::Endpoint; 7 - pub use index::Index;