Rust library to generate static websites
at fix/misc-errors 132 lines 4.7 kB view raw
1use maud::{Markup, html}; 2use maudit::{ 3 content::MarkdownHeading, 4 route::{PageContext, RouteExt}, 5}; 6 7use crate::{ 8 content::{DocsContent, DocsSection}, 9 routes::{DocsPage, DocsPageParams}, 10}; 11 12pub fn left_sidebar(ctx: &mut PageContext) -> Markup { 13 let content = ctx.content.get_source::<DocsContent>("docs"); 14 15 let mut sections = std::collections::HashMap::new(); 16 17 for entry in content.entries.iter() { 18 if let Some(section) = &entry.data(ctx).section { 19 sections.entry(section).or_insert_with(Vec::new).push(entry); 20 } 21 } 22 23 let mut sections: Vec<_> = sections.into_iter().collect(); 24 25 // TODO: Implement sorting on the enum ord itself? 26 sections.sort_by_key(|(section, _)| { 27 // Define sort order 28 match section { 29 DocsSection::GettingStarted => 0, 30 DocsSection::CoreConcepts => 1, 31 DocsSection::Guide => 2, 32 DocsSection::Advanced => 3, 33 } 34 }); 35 36 let static_links: Vec<(&str, &str)> = vec![ 37 ("Reference", "https://docs.rs/maudit"), 38 ( 39 "Examples", 40 "https://github.com/bruits/maudit/tree/main/examples", 41 ), 42 ]; 43 44 let entries = sections.iter().map(|(section, entries)| { 45 html! { 46 li.mb-6.sm:mb-4 { 47 h2.text-xl.sm:text-lg.font-bold { (section) } 48 ul { 49 @for entry in entries { 50 @let url = DocsPage.url(DocsPageParams { slug: entry.id.clone() }); 51 @let is_current_page = url == *ctx.current_path; 52 li { 53 @let base_classes = "block py-2 sm:py-1 px-4 sm:px-3 text-lg sm:text-base font-medium sm:font-normal transition-colors border-b border-borders sm:border-0"; 54 @let conditional_classes = if is_current_page { 55 "text-brand-red sm:border-l-2 sm:border-l-brand-red" 56 } else { 57 "text-our-black hover:text-brand-red sm:border-l-2 sm:border-l-borders sm:hover:border-l-brand-red" 58 }; 59 a class=(format!("{} {}", base_classes, conditional_classes)) href=(url) { 60 (entry.data(ctx).title) 61 } 62 } 63 } 64 } 65 } 66 } 67 }); 68 69 html! { 70 ul.mb-6.sm:mb-4.space-y-0.sm:space-y-1 { 71 @for (name, link) in static_links { 72 li { 73 a.block.py-2.sm:py-0.px-4.sm:px-0.text-xl.sm:text-lg.font-medium.text-our-black.border-b.border-borders.sm:border-0.transition-colors."hover:text-brand-red".sm:bg-transparent.sm:hover:bg-transparent href=(link) { (name) } 74 } 75 } 76 } 77 ul.space-y-1 { 78 @for entry in entries { 79 (entry) 80 } 81 } 82 } 83} 84 85pub fn right_sidebar(headings: &[MarkdownHeading]) -> Markup { 86 let mut html_headings: Vec<maud::PreEscaped<String>> = Vec::new(); 87 let mut i = 0; 88 let mut seen_h2 = false; 89 while i < headings.len() { 90 let heading = &headings[i]; 91 let (pad, border) = match heading.level { 92 2 => ("pl-0", ""), // h2 93 3 => ("pl-4", "sm:border-l-2 sm:border-borders"), // h3 94 4 => ("pl-8", "sm:border-l-2 sm:border-borders"), // h4 95 5 => ("pl-12", "sm:border-l-2 sm:border-borders"), // h5 96 6 => ("pl-16", "sm:border-l-2 sm:border-borders"), // h6 97 _ => ("pl-0", ""), // fallback 98 }; 99 let next_level = if i + 1 < headings.len() { 100 headings[i + 1].level 101 } else { 102 0 103 }; 104 let margin_top = if heading.level == 2 && next_level > 2 && seen_h2 { 105 "mt-4" 106 } else { 107 "" 108 }; 109 if heading.level == 2 { 110 seen_h2 = true; 111 } 112 html_headings.push(html! { 113 li.(border).(margin_top) { 114 a class=(format!("block py-1 px-3 sm:py-0 text-lg sm:text-base transition-colors hover:bg-gray-50 sm:hover:bg-transparent hover:text-brand-red border-b border-borders sm:border-b-0 {}", pad)) href=(format!("#{}", heading.id)) { 115 (heading.title) 116 } 117 } 118 }); 119 i += 1; 120 } 121 122 html!( 123 h2.text-xl.sm:text-lg.font-bold.mb-4.sm:mb-0 { "On This Page" } 124 nav.sticky.top-8 { 125 ul { 126 @for heading in html_headings { 127 (heading) 128 } 129 } 130 } 131 ) 132}