The (very WIP) home of the next versions of my web presences
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Rip out the `Component` bits. It doesn’t work, so: try something else.

+27 -139
+1 -9
lx/src/archive.rs
··· 1 use chrono::{Datelike, Month}; 2 use indexmap::{IndexMap, IndexSet}; 3 - use minijinja::Environment; 4 use serde::Serialize; 5 use thiserror::Error; 6 7 - use crate::{ 8 - page::{Item, PostLink}, 9 - templates::component::Component, 10 - }; 11 12 /// A data structure that maps each post to Y -> M -> D -> posts, preserving the order of 13 /// the posts. ··· 42 43 Ok(Archive(year_map)) 44 } 45 - } 46 - 47 - impl<'e> Component for Archive<'e> { 48 - const VIEW_NAME: &'static str = "archive"; 49 } 50 51 #[allow(dead_code)]
··· 1 use chrono::{Datelike, Month}; 2 use indexmap::{IndexMap, IndexSet}; 3 use serde::Serialize; 4 use thiserror::Error; 5 6 + use crate::page::{Item, PostLink}; 7 8 /// A data structure that maps each post to Y -> M -> D -> posts, preserving the order of 9 /// the posts. ··· 38 39 Ok(Archive(year_map)) 40 } 41 } 42 43 #[allow(dead_code)]
+2 -28
lx/src/data/config.rs
··· 44 pub use serial::NavItem; 45 46 pub mod serial { 47 - use std::{collections::HashMap, fmt::Display, sync::Arc}; 48 49 use camino::{Utf8Path, Utf8PathBuf}; 50 - use minijinja::{Environment, State, Value, value::Object}; 51 use normalize_path::NormalizePath as _; 52 use serde::{Deserialize, Serialize}; 53 use thiserror::Error; 54 55 - use crate::{data::email::Email, templates::component::Component}; 56 57 #[derive(Serialize, Deserialize, Debug)] 58 pub struct Config { ··· 117 pub enum NavItem { 118 Separator, 119 Page { title: String, path: String }, 120 - } 121 - 122 - // NOTE(2025-10-09): this currently never gets hit when accessing via a template 123 - // invocation that goes through `Config`, because `Config` and `NavItem` both 124 - // implement `Serialize`, and so by the time the renderer is working with the 125 - // `Config::nav` data, it is working with it as the *serialized* version of it, 126 - // which means it never actually has a chance to see the `Component` version of it. 127 - // In practice, this likely means that I need to get rid of the `Serialize` bound on 128 - // `Component` and require custom rendering at each site (ugh) or find some other 129 - // way to express these kinds of relations. _Le sigh_. 130 - // 131 - // TODO: also maybe move this elsewhere? 132 - impl Component for NavItem { 133 - const VIEW_NAME: &'static str = "nav-item"; 134 - } 135 - 136 - impl Object for NavItem { 137 - fn call( 138 - self: &Arc<Self>, 139 - state: &State<'_, '_>, 140 - _args: &[Value], 141 - ) -> Result<Value, minijinja::Error> { 142 - println!("got here?"); 143 - self.view(state.env()).map(Value::from) 144 - } 145 } 146 147 #[derive(Error, Debug)]
··· 44 pub use serial::NavItem; 45 46 pub mod serial { 47 + use std::{collections::HashMap, fmt::Display}; 48 49 use camino::{Utf8Path, Utf8PathBuf}; 50 use normalize_path::NormalizePath as _; 51 use serde::{Deserialize, Serialize}; 52 use thiserror::Error; 53 54 + use crate::data::email::Email; 55 56 #[derive(Serialize, Deserialize, Debug)] 57 pub struct Config { ··· 116 pub enum NavItem { 117 Separator, 118 Page { title: String, path: String }, 119 } 120 121 #[derive(Error, Debug)]
-27
lx/src/data/item/mod.rs
··· 6 use camino::{Utf8Path, Utf8PathBuf}; 7 use chrono::{DateTime, FixedOffset}; 8 use lx_md::Markdown; 9 - use minijinja::Environment; 10 use serde::{Deserialize, Serialize}; 11 use slug::slugify; 12 use thiserror::Error; ··· 15 use crate::{ 16 archive::Archive, 17 page::{self, Item}, 18 - templates::component::Component, 19 }; 20 21 use self::cascade::Cascade; ··· 233 } 234 } 235 236 - impl Component for Qualifiers { 237 - const VIEW_NAME: &'static str = "qualifiers"; 238 - 239 - fn view(&self, env: &Environment) -> Result<String, minijinja::Error> { 240 - env.get_template(&Self::template())?.render(self) 241 - } 242 - } 243 - 244 #[derive(Debug, Serialize, Deserialize, PartialEq)] 245 pub struct Book { 246 title: Option<String>, ··· 304 struct BookView<'a> { 305 book: &'a Book, 306 archive: Archive<'a>, 307 - } 308 - 309 - impl<'a> Component for BookView<'a> { 310 - const VIEW_NAME: &'static str = "book"; 311 - 312 - fn view(&self, env: &Environment) -> Result<String, minijinja::Error> { 313 - let rendered_archive = self.archive.view(env)?; 314 - 315 - let rendered = env 316 - .get_template(Self::VIEW_NAME)? 317 - .render(minijinja::context! { 318 - book => self.book, 319 - archive => rendered_archive, 320 - })?; 321 - 322 - Ok(rendered) 323 - } 324 } 325 326 #[derive(Debug, Serialize, Deserialize)]
··· 6 use camino::{Utf8Path, Utf8PathBuf}; 7 use chrono::{DateTime, FixedOffset}; 8 use lx_md::Markdown; 9 use serde::{Deserialize, Serialize}; 10 use slug::slugify; 11 use thiserror::Error; ··· 14 use crate::{ 15 archive::Archive, 16 page::{self, Item}, 17 }; 18 19 use self::cascade::Cascade; ··· 231 } 232 } 233 234 #[derive(Debug, Serialize, Deserialize, PartialEq)] 235 pub struct Book { 236 title: Option<String>, ··· 294 struct BookView<'a> { 295 book: &'a Book, 296 archive: Archive<'a>, 297 } 298 299 #[derive(Debug, Serialize, Deserialize)]
+1 -8
lx/src/data/item/serial.rs
··· 11 use serde::{Deserialize, Serialize}; 12 use thiserror::Error; 13 14 - use crate::{ 15 - data::{image::serial::Image, item::nice_list}, 16 - templates::component::Component, 17 - }; 18 19 #[derive(Deserialize, Debug, Default)] 20 pub struct Item { ··· 92 pub discusses: Vec<String>, 93 pub disclosure: Option<String>, 94 pub retraction: Option<Retraction>, 95 - } 96 - 97 - impl Component for Qualifiers { 98 - const VIEW_NAME: &'static str = "qualifiers"; 99 } 100 101 #[derive(Serialize, Deserialize, Clone, Debug)]
··· 11 use serde::{Deserialize, Serialize}; 12 use thiserror::Error; 13 14 + use crate::data::{image::serial::Image, item::nice_list}; 15 16 #[derive(Deserialize, Debug, Default)] 17 pub struct Item { ··· 89 pub discusses: Vec<String>, 90 pub disclosure: Option<String>, 91 pub retraction: Option<Retraction>, 92 } 93 94 #[derive(Serialize, Deserialize, Clone, Debug)]
+4 -22
lx/src/page.rs
··· 1 - use crate::{ 2 - data::{ 3 - config::Config, 4 - item::{self, Metadata, Slug, cascade::Cascade, serial}, 5 - }, 6 - templates::component::Component, 7 }; 8 use camino::{Utf8Path, Utf8PathBuf}; 9 use chrono::{DateTime, FixedOffset}; 10 use json_feed::Author; 11 use lx_md::{self, Markdown, RenderError, ToRender}; 12 - use minijinja::{Environment, State, Value, context, value::Object}; 13 use serde::{Deserialize, Serialize}; 14 - use std::{cmp::Ordering, sync::Arc}; 15 use std::{collections::HashMap, fmt, hash::Hash, os::unix::prelude::OsStrExt}; 16 use thiserror::Error; 17 use uuid::Uuid; ··· 242 slug: &value.page.data.slug, 243 } 244 } 245 - } 246 - 247 - impl Object for PostLink<'_> { 248 - fn call( 249 - self: &Arc<Self>, 250 - state: &State<'_, '_>, 251 - _args: &[Value], 252 - ) -> Result<Value, minijinja::Error> { 253 - self.view(state.env()).map(Value::from) 254 - } 255 - } 256 - 257 - impl<'e> Component for PostLink<'e> { 258 - const VIEW_NAME: &'static str = "post-link"; 259 } 260 261 #[derive(Error, Debug)]
··· 1 + use crate::data::{ 2 + config::Config, 3 + item::{self, Metadata, Slug, cascade::Cascade, serial}, 4 }; 5 use camino::{Utf8Path, Utf8PathBuf}; 6 use chrono::{DateTime, FixedOffset}; 7 use json_feed::Author; 8 use lx_md::{self, Markdown, RenderError, ToRender}; 9 use serde::{Deserialize, Serialize}; 10 + use std::cmp::Ordering; 11 use std::{collections::HashMap, fmt, hash::Hash, os::unix::prelude::OsStrExt}; 12 use thiserror::Error; 13 use uuid::Uuid; ··· 238 slug: &value.page.data.slug, 239 } 240 } 241 } 242 243 #[derive(Error, Debug)]
-14
lx/src/templates/component.rs
··· 1 - use minijinja::Environment; 2 - use serde::Serialize; 3 - 4 - pub(crate) trait Component: Serialize + Sized { 5 - const VIEW_NAME: &'static str; 6 - 7 - fn view(&self, env: &Environment) -> Result<String, minijinja::Error> { 8 - env.get_template(&Self::template())?.render(self) 9 - } 10 - 11 - fn template() -> String { 12 - format!("components/{}.jinja", Self::VIEW_NAME) 13 - } 14 - }
···
+19 -30
lx/src/templates/functions.rs
··· 1 use std::{fmt, sync::Arc}; 2 3 use minijinja::{ 4 - State, Value, context, 5 value::{Object, Rest, ViaDeserialize}, 6 }; 7 - use simplelog::debug; 8 9 use crate::{ 10 data::{config::Config, image::Image, item::Metadata}, 11 - page::{self, RootedPath}, 12 - templates::component::{self, Component}, 13 }; 14 15 pub(crate) fn add_all(env: &mut minijinja::Environment<'_>) { ··· 102 } 103 104 /// Data for the `twitter:(label|data)(1|2)` meta tags. 105 - #[derive(Debug, serde::Serialize)] 106 enum Label { 107 Post { 108 tags: Vec<String>, ··· 139 // here given it’s pretty obviously just me on my own site? 140 pub fn label1(&self) -> &str { 141 match self { 142 - Label::Post { .. } => "Author", 143 Label::Work { .. } => "Instrumentation", 144 Label::Custom { label1, .. } => label1.as_str(), 145 } ··· 172 } 173 } 174 175 - impl From<Label> for Value { 176 - fn from(val: Label) -> Self { 177 - Value::from_object(val) 178 - } 179 - } 180 - 181 - impl Component for Label { 182 - const VIEW_NAME: &'static str = "twitter-label"; 183 - 184 - fn view(&self, env: &minijinja::Environment) -> Result<String, minijinja::Error> { 185 - env.get_template(&Self::template())?.render(context! { 186 - label1 => self.label1(), 187 - label2 => self.label2(), 188 - data1 => self.data1(), 189 - data2 => self.data2(), 190 - }) 191 - } 192 - } 193 - 194 impl Object for Label { 195 - fn call( 196 - self: &Arc<Self>, 197 - state: &State<'_, '_>, 198 _args: &[Value], 199 ) -> Result<Value, minijinja::Error> { 200 - self.view(state.env()).map(Value::from) 201 } 202 } 203 204 - #[derive(Debug, serde::Serialize)] 205 struct ApproximateLength { 206 rounded: u64, 207 }
··· 1 use std::{fmt, sync::Arc}; 2 3 use minijinja::{ 4 + State, Value, 5 value::{Object, Rest, ViaDeserialize}, 6 }; 7 8 use crate::{ 9 data::{config::Config, image::Image, item::Metadata}, 10 + page::RootedPath, 11 }; 12 13 pub(crate) fn add_all(env: &mut minijinja::Environment<'_>) { ··· 100 } 101 102 /// Data for the `twitter:(label|data)(1|2)` meta tags. 103 + #[derive(Debug, serde::Serialize, serde::Deserialize)] 104 enum Label { 105 Post { 106 tags: Vec<String>, ··· 137 // here given it’s pretty obviously just me on my own site? 138 pub fn label1(&self) -> &str { 139 match self { 140 + Label::Post { .. } => "Tags", 141 Label::Work { .. } => "Instrumentation", 142 Label::Custom { label1, .. } => label1.as_str(), 143 } ··· 170 } 171 } 172 173 impl Object for Label { 174 + fn call_method( 175 + self: &Arc<Label>, 176 + _state: &State, 177 + name: &str, 178 _args: &[Value], 179 ) -> Result<Value, minijinja::Error> { 180 + match name { 181 + "label1" => Ok(self.label1().into()), 182 + "data1" => Ok(self.data1().into()), 183 + "label2" => Ok(self.label2().into()), 184 + "data2" => Ok(self.data2().into()), 185 + _ => Err(minijinja::Error::new( 186 + minijinja::ErrorKind::UnknownMethod, 187 + name.to_owned(), 188 + )), 189 + } 190 } 191 } 192 193 + #[derive(Debug, serde::Serialize, serde::Deserialize)] 194 struct ApproximateLength { 195 rounded: u64, 196 }
-1
lx/src/templates/mod.rs
··· 1 - pub mod component; 2 mod filters; 3 mod functions; 4
··· 1 mod filters; 2 mod functions; 3