diff --git a/web/index.html b/web/index.html index b223fc9..08ad6fd 100644 --- a/web/index.html +++ b/web/index.html @@ -143,6 +143,9 @@ blockquote[type="cite"], .tags-menu .menu-list a { padding: 0.25em 0.5em; } +.tags-menu .tag-indent { + padding-left: 1em; +} .navbar { border: none; } diff --git a/web/src/lib.rs b/web/src/lib.rs index 2186ec7..759eca8 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -1235,6 +1235,24 @@ fn view_desktop(model: &Model) -> Node { pager, } => view_search_results(&query, results.as_slice(), *count, pager), }; + fn view_tag_li(display_name: &str, indent: usize, t: &Tag) -> Node { + li![a![ + attrs! { + At::Href => urls::search(&format!("tag:{}", t.name), 0) + }, + style! { + St::BackgroundColor => t.bg_color, + St::Color => t.fg_color, + }, + (0..indent).map(|_| span![C!["tag-indent"], ""]), + display_name + ]] + } + fn matches(a: &[&str], b: &[&str]) -> usize { + std::iter::zip(a.iter(), b.iter()) + .take_while(|(a, b)| a == b) + .count() + } div![ C!["desktop-main-content"], aside![ @@ -1242,16 +1260,38 @@ fn view_desktop(model: &Model) -> Node { p![C!["menu-label"], "Tags"], ul![ C!["menu-list"], - model.tags.as_ref().map(|tags| tags.iter().map(|t| li![a![ - attrs! { - At::Href => urls::search(&format!("tag:{}", t.name), 0) - }, - style! { - St::BackgroundColor => t.bg_color, - St::Color => t.fg_color, - }, - &t.name - ]])) + model.tags.as_ref().map(|tags| { + let mut lis = Vec::new(); + let mut last = Vec::new(); + for t in tags { + let parts: Vec<_> = t.name.split('/').collect(); + let mut n = matches(&last, &parts); + if t.name.starts_with("ZZCrap/Free") { + info!("n: {n}, parts: {parts:?} last: {last:?}"); + } + if n <= parts.len() - 2 && parts.len() > 1 { + // Synthesize fake tags for proper indenting. + for i in n..parts.len() - 1 { + let display_name = parts[n]; + lis.push(view_tag_li( + &display_name, + n, + &Tag { + name: parts[..i + 1].join("/"), + bg_color: "#000".to_string(), + fg_color: "#fff".to_string(), + }, + )); + } + last = parts[..parts.len() - 1].to_vec(); + n = parts.len() - 1; + } + let display_name = parts[n]; + lis.push(view_tag_li(&display_name, n, t)); + last = parts; + } + lis + }) ] ], div![