add tag display to sidebar
This commit is contained in:
		
							parent
							
								
									f5d6c9c05b
								
							
						
					
					
						commit
						a2debf5b2c
					
				
					 3 changed files with 46 additions and 3 deletions
				
			
		
							
								
								
									
										31
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										31
									
								
								src/main.rs
									
										
									
									
									
								
							|  | @ -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, | ||||||
|     }) |     }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue