From d466f531ebe117c3a83410f9ff74fc4865b036fc Mon Sep 17 00:00:00 2001 From: slonkazoid Date: Wed, 1 May 2024 23:12:52 +0300 Subject: [PATCH] add tags and cache versioning --- src/filters.rs | 25 ++++++++++++++++++++++++- src/main.rs | 8 +++++++- src/post/cache.rs | 18 ++++++++++++++++-- src/post/mod.rs | 7 ++++--- static/style.css | 7 +++++-- templates/index.html | 24 ++++++++++++++---------- templates/macros.askama | 19 +++++++++++++++++++ templates/post.html | 8 ++------ 8 files changed, 91 insertions(+), 25 deletions(-) create mode 100644 templates/macros.askama diff --git a/src/filters.rs b/src/filters.rs index 75d39cf..35929dc 100644 --- a/src/filters.rs +++ b/src/filters.rs @@ -1,7 +1,9 @@ -use std::time::Duration; +use std::{collections::HashMap, time::Duration}; use chrono::{DateTime, TimeZone}; +use crate::post::PostMetadata; + pub fn date(date: &DateTime) -> Result { Ok(date.to_rfc3339_opts(chrono::SecondsFormat::Secs, true)) } @@ -9,3 +11,24 @@ pub fn date(date: &DateTime) -> Result { pub fn duration(duration: &&Duration) -> Result { Ok(format!("{:?}", duration)) } + +pub fn collect_tags(posts: &Vec) -> Result, askama::Error> { + let mut tags = HashMap::new(); + + for post in posts { + for tag in &post.tags { + if let Some((existing_tag, count)) = tags.remove_entry(tag) { + tags.insert(existing_tag, count + 1); + } else { + tags.insert(tag.clone(), 1); + } + } + } + + let mut tags: Vec<(String, u64)> = tags.into_iter().collect(); + + tags.sort_unstable_by_key(|(v, _)| v.clone()); + tags.sort_by_key(|(_, v)| -(*v as i64)); + + Ok(tags) +} diff --git a/src/main.rs b/src/main.rs index 4f0a0db..d94fcab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,6 +37,7 @@ use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilte use crate::config::Config; use crate::error::{AppResult, PostError}; +use crate::post::cache::{Cache, CACHE_VERSION}; use crate::post::{PostManager, PostMetadata, RenderStats}; type ArcState = Arc; @@ -179,8 +180,13 @@ async fn main() -> eyre::Result<()> { .context("failed to read cache file")?; buf }; - let cache = + let mut cache: Cache = bitcode::deserialize(serialized.as_slice()).context("failed to parse cache")?; + if cache.version() < CACHE_VERSION { + warn!("cache version changed, clearing cache"); + cache = Cache::default(); + }; + Ok::(PostManager::new_with_cache( config.dirs.posts.clone(), config.render.clone(), diff --git a/src/post/cache.rs b/src/post/cache.rs index 2143538..6437aa3 100644 --- a/src/post/cache.rs +++ b/src/post/cache.rs @@ -7,6 +7,9 @@ use tracing::{debug, instrument}; use crate::config::RenderConfig; use crate::post::PostMetadata; +/// do not persist cache if this version number changed +pub const CACHE_VERSION: u16 = 1; + #[derive(Serialize, Deserialize, Clone)] pub struct CacheValue { pub metadata: PostMetadata, @@ -15,8 +18,14 @@ pub struct CacheValue { config_hash: u64, } -#[derive(Serialize, Deserialize, Default, Clone)] -pub struct Cache(HashMap); +#[derive(Serialize, Deserialize, Clone)] +pub struct Cache(HashMap, u16); + +impl Default for Cache { + fn default() -> Self { + Self(Default::default(), CACHE_VERSION) + } +} impl Cache { pub async fn lookup( @@ -117,4 +126,9 @@ impl Cache { let new_size = self.0.len(); debug!("removed {i} entries ({old_size} -> {new_size} entries)"); } + + #[inline(always)] + pub fn version(&self) -> u16 { + self.1 + } } diff --git a/src/post/mod.rs b/src/post/mod.rs index bdf6e3c..ceed862 100644 --- a/src/post/mod.rs +++ b/src/post/mod.rs @@ -1,5 +1,6 @@ -mod cache; +pub mod cache; +use std::collections::BTreeSet; use std::io; use std::path::{Path, PathBuf}; use std::time::{Duration, Instant, SystemTime}; @@ -27,7 +28,7 @@ struct FrontMatter { pub created_at: Option>, pub modified_at: Option>, #[serde(default)] - pub tags: Vec, + pub tags: BTreeSet, } impl FrontMatter { @@ -45,7 +46,7 @@ impl FrontMatter { icon: self.icon, created_at: self.created_at.or_else(|| created.map(|t| t.into())), modified_at: self.modified_at.or_else(|| modified.map(|t| t.into())), - tags: self.tags, + tags: self.tags.into_iter().collect(), } } } diff --git a/static/style.css b/static/style.css index 84991ba..21633a7 100644 --- a/static/style.css +++ b/static/style.css @@ -30,8 +30,7 @@ :root, code { /* please have one at least one good monospace font */ - font-family: "Hack", "Hack Nerd Font", "JetBrains Mono", - "JetBrainsMono Nerd Font", "Ubuntu Mono", monospace, sans-serif; + font-family: "Hack", "Hack Nerd Font", "JetBrains Mono", "JetBrainsMono Nerd Font", "Ubuntu Mono", monospace, sans-serif; } :root { @@ -81,6 +80,10 @@ footer { opacity: 0.65; } +div.post { + margin-bottom: 1em; +} + /* BEGIN cool effect everyone liked */ body { diff --git a/templates/index.html b/templates/index.html index 4315cca..4292de8 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,3 +1,4 @@ +{%- import "macros.askama" as macros -%} @@ -16,21 +17,24 @@

posts

- {% for post in posts %} -

+ {% for post in posts %} +

{{ post.title }}
{{ post.description }}
- {% match post.created_at %} {% when Some(created_at) %} - written:       {{ created_at|date }}
- {% when None %} {% endmatch %} - {% match post.modified_at %} {% when Some(modified_at) %} - last modified: {{ modified_at|date }} - {% when None %} {% endmatch %} -

- {% endfor %} + {% call macros::table(post) %} +
+ {% endfor %}
+ {% let tags = posts|collect_tags %} + {% if !tags.is_empty() %} +

tags

+ {% endif %} + {% for tag in tags %} + {{ tag.0 }} +
+ {% endfor %} diff --git a/templates/macros.askama b/templates/macros.askama new file mode 100644 index 0000000..17be7a6 --- /dev/null +++ b/templates/macros.askama @@ -0,0 +1,19 @@ +{% macro table(post) %} + {% match post.created_at %} + {% when Some(created_at) %} + written:       {{ created_at|date }}
+ {% when None %} + {% endmatch %} + {% match post.modified_at %} + {% when Some(modified_at) %} + last modified: {{ modified_at|date }}
+ {% when None %} + {% endmatch %} + + {% if !post.tags.is_empty() %} + tags:          + {% for tag in post.tags %} + {{ tag }} + {% endfor %}
+ {% endif %} +{% endmacro %} diff --git a/templates/post.html b/templates/post.html index f851db7..d148e5f 100644 --- a/templates/post.html +++ b/templates/post.html @@ -1,3 +1,4 @@ +{%- import "macros.askama" as macros -%}

{{ meta.title }} @@ -6,12 +7,7 @@

- {% match meta.created_at %} {% when Some(created_at) %} - written:       {{ created_at|date }}
- {% when None %} {% endmatch %} - {% match meta.modified_at %} {% when Some(modified_at) %} - last modified: {{ modified_at|date }} - {% when None %} {% endmatch %} + {% call macros::table(meta) %}
link
back to home