add tag display to sidebar

master
Tomáš Mládek 2021-10-05 22:34:29 +02:00
parent f5d6c9c05b
commit a2debf5b2c
3 changed files with 46 additions and 3 deletions

View File

@ -14,6 +14,7 @@ use percent_encoding::{percent_decode_str, utf8_percent_encode};
use pulldown_cmark::{html, Event, Options, Parser, Tag}; use pulldown_cmark::{html, Event, Options, Parser, Tag};
use regex::{Captures, Regex}; use regex::{Captures, Regex};
use slug::slugify; use slug::slugify;
use std::cmp::Reverse;
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::File; use std::fs::File;
use std::io::Read; use std::io::Read;
@ -44,6 +45,7 @@ struct MutableState {
struct GardenCache { struct GardenCache {
pages: HashMap<String, ParsedPage>, pages: HashMap<String, ParsedPage>,
files: Vec<PathBuf>, files: Vec<PathBuf>,
tags: HashMap<String, u32>,
} }
impl Default for GardenCache { impl Default for GardenCache {
@ -51,6 +53,7 @@ impl Default for GardenCache {
GardenCache { GardenCache {
pages: HashMap::new(), pages: HashMap::new(),
files: vec![], files: vec![],
tags: HashMap::new(),
} }
} }
} }
@ -297,6 +300,12 @@ async fn render(
data.title.as_ref().unwrap_or(&"Digital Garden".to_string()), data.title.as_ref().unwrap_or(&"Digital Garden".to_string()),
); );
context.insert("files", &cache.files); context.insert("files", &cache.files);
let mut tags: Vec<(&String, &u32)> = cache.tags.iter().collect();
tags.sort_by_key(|(t, _)| *t);
tags.sort_by_key(|(_, n)| Reverse(*n));
context.insert("tags", &tags);
context.insert( context.insert(
"recently_changed", "recently_changed",
&recently_changed &recently_changed
@ -387,6 +396,7 @@ fn update_garden<P: AsRef<Path>>(
} }
let mut pages = current.pages; let mut pages = current.pages;
let mut tags = current.tags;
let markdown_paths = files let markdown_paths = files
.iter() .iter()
@ -428,9 +438,13 @@ fn update_garden<P: AsRef<Path>>(
}, },
}, },
); );
result.tags.into_iter().for_each(|tag| {
*tags.entry(tag).or_insert(0) += 1;
});
} }
let result = GardenCache { pages, files }; let result = GardenCache { pages, files, tags };
trace!("{:#?}", result); trace!("{:#?}", result);
Ok(result) Ok(result)
} }
@ -439,6 +453,7 @@ struct ParseResult {
html: String, html: String,
title: Option<String>, title: Option<String>,
links: Vec<String>, links: Vec<String>,
tags: Vec<String>,
} }
fn parse_garden<S: AsRef<str>>(text: S) -> anyhow::Result<ParseResult> { fn parse_garden<S: AsRef<str>>(text: S) -> anyhow::Result<ParseResult> {
@ -448,10 +463,19 @@ fn parse_garden<S: AsRef<str>>(text: S) -> anyhow::Result<ParseResult> {
let mut last_nontext_event: Option<Event> = None; let mut last_nontext_event: Option<Event> = None;
let mut links: Vec<String> = vec![]; let mut links: Vec<String> = vec![];
let mut tags: Vec<String> = vec![];
let parser = Parser::new_ext(text.as_ref(), Options::all()).map(|event| { let parser = Parser::new_ext(text.as_ref(), Options::all()).map(|event| {
if let Event::Start(Tag::Link(_, str, _)) = &event { if let Event::Start(Tag::Link(_, dest, _)) = &event {
links.push(str.to_string()); links.push(dest.to_string());
}
if let Some(Event::Start(Tag::Link(_, dest, _))) = &last_nontext_event {
if let Event::Text(str) = &event {
if str.starts_with("#") {
tags.push(dest.to_string());
}
}
} }
if let Some(Event::Start(Tag::Heading(hl))) = last_nontext_event { if let Some(Event::Start(Tag::Heading(hl))) = last_nontext_event {
@ -476,6 +500,7 @@ fn parse_garden<S: AsRef<str>>(text: S) -> anyhow::Result<ParseResult> {
html, html,
title: top_heading_text, title: top_heading_text,
links, links,
tags,
}) })
} }

View File

@ -183,6 +183,10 @@ nav .graph-view {
text-align: center; text-align: center;
} }
.tag .count {
opacity: .5;
}
footer { footer {
padding: 1em 0; padding: 1em 0;
color: gray; color: gray;

View File

@ -73,6 +73,20 @@
{% endfor %} {% endfor %}
</ul> </ul>
</section> </section>
{% if tags %}
<section>
<h2>Tags</h2>
<ul>
{% for tag_cnt in tags %}
<li class="tag">
<a href="/{{tag_cnt.0}}">
<span class="label">#{{tag_cnt.0}}</span> <span class="count">({{tag_cnt.1}})</span>
</a>
</li>
{% endfor %}
</ul>
</section>
{% endif %}
<section class="graph-view"> <section class="graph-view">
<a href="/!graph">Graph view (beta)</a> <a href="/!graph">Graph view (beta)</a>
</section> </section>