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

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

Changed files
+27 -139
lx
+1 -9
lx/src/archive.rs
··· 1 1 use chrono::{Datelike, Month}; 2 2 use indexmap::{IndexMap, IndexSet}; 3 - use minijinja::Environment; 4 3 use serde::Serialize; 5 4 use thiserror::Error; 6 5 7 - use crate::{ 8 - page::{Item, PostLink}, 9 - templates::component::Component, 10 - }; 6 + use crate::page::{Item, PostLink}; 11 7 12 8 /// A data structure that maps each post to Y -> M -> D -> posts, preserving the order of 13 9 /// the posts. ··· 42 38 43 39 Ok(Archive(year_map)) 44 40 } 45 - } 46 - 47 - impl<'e> Component for Archive<'e> { 48 - const VIEW_NAME: &'static str = "archive"; 49 41 } 50 42 51 43 #[allow(dead_code)]
+2 -28
lx/src/data/config.rs
··· 44 44 pub use serial::NavItem; 45 45 46 46 pub mod serial { 47 - use std::{collections::HashMap, fmt::Display, sync::Arc}; 47 + use std::{collections::HashMap, fmt::Display}; 48 48 49 49 use camino::{Utf8Path, Utf8PathBuf}; 50 - use minijinja::{Environment, State, Value, value::Object}; 51 50 use normalize_path::NormalizePath as _; 52 51 use serde::{Deserialize, Serialize}; 53 52 use thiserror::Error; 54 53 55 - use crate::{data::email::Email, templates::component::Component}; 54 + use crate::data::email::Email; 56 55 57 56 #[derive(Serialize, Deserialize, Debug)] 58 57 pub struct Config { ··· 117 116 pub enum NavItem { 118 117 Separator, 119 118 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 119 } 146 120 147 121 #[derive(Error, Debug)]
-27
lx/src/data/item/mod.rs
··· 6 6 use camino::{Utf8Path, Utf8PathBuf}; 7 7 use chrono::{DateTime, FixedOffset}; 8 8 use lx_md::Markdown; 9 - use minijinja::Environment; 10 9 use serde::{Deserialize, Serialize}; 11 10 use slug::slugify; 12 11 use thiserror::Error; ··· 15 14 use crate::{ 16 15 archive::Archive, 17 16 page::{self, Item}, 18 - templates::component::Component, 19 17 }; 20 18 21 19 use self::cascade::Cascade; ··· 233 231 } 234 232 } 235 233 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 234 #[derive(Debug, Serialize, Deserialize, PartialEq)] 245 235 pub struct Book { 246 236 title: Option<String>, ··· 304 294 struct BookView<'a> { 305 295 book: &'a Book, 306 296 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 297 } 325 298 326 299 #[derive(Debug, Serialize, Deserialize)]
+1 -8
lx/src/data/item/serial.rs
··· 11 11 use serde::{Deserialize, Serialize}; 12 12 use thiserror::Error; 13 13 14 - use crate::{ 15 - data::{image::serial::Image, item::nice_list}, 16 - templates::component::Component, 17 - }; 14 + use crate::data::{image::serial::Image, item::nice_list}; 18 15 19 16 #[derive(Deserialize, Debug, Default)] 20 17 pub struct Item { ··· 92 89 pub discusses: Vec<String>, 93 90 pub disclosure: Option<String>, 94 91 pub retraction: Option<Retraction>, 95 - } 96 - 97 - impl Component for Qualifiers { 98 - const VIEW_NAME: &'static str = "qualifiers"; 99 92 } 100 93 101 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, 1 + use crate::data::{ 2 + config::Config, 3 + item::{self, Metadata, Slug, cascade::Cascade, serial}, 7 4 }; 8 5 use camino::{Utf8Path, Utf8PathBuf}; 9 6 use chrono::{DateTime, FixedOffset}; 10 7 use json_feed::Author; 11 8 use lx_md::{self, Markdown, RenderError, ToRender}; 12 - use minijinja::{Environment, State, Value, context, value::Object}; 13 9 use serde::{Deserialize, Serialize}; 14 - use std::{cmp::Ordering, sync::Arc}; 10 + use std::cmp::Ordering; 15 11 use std::{collections::HashMap, fmt, hash::Hash, os::unix::prelude::OsStrExt}; 16 12 use thiserror::Error; 17 13 use uuid::Uuid; ··· 242 238 slug: &value.page.data.slug, 243 239 } 244 240 } 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 241 } 260 242 261 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 1 use std::{fmt, sync::Arc}; 2 2 3 3 use minijinja::{ 4 - State, Value, context, 4 + State, Value, 5 5 value::{Object, Rest, ViaDeserialize}, 6 6 }; 7 - use simplelog::debug; 8 7 9 8 use crate::{ 10 9 data::{config::Config, image::Image, item::Metadata}, 11 - page::{self, RootedPath}, 12 - templates::component::{self, Component}, 10 + page::RootedPath, 13 11 }; 14 12 15 13 pub(crate) fn add_all(env: &mut minijinja::Environment<'_>) { ··· 102 100 } 103 101 104 102 /// Data for the `twitter:(label|data)(1|2)` meta tags. 105 - #[derive(Debug, serde::Serialize)] 103 + #[derive(Debug, serde::Serialize, serde::Deserialize)] 106 104 enum Label { 107 105 Post { 108 106 tags: Vec<String>, ··· 139 137 // here given it’s pretty obviously just me on my own site? 140 138 pub fn label1(&self) -> &str { 141 139 match self { 142 - Label::Post { .. } => "Author", 140 + Label::Post { .. } => "Tags", 143 141 Label::Work { .. } => "Instrumentation", 144 142 Label::Custom { label1, .. } => label1.as_str(), 145 143 } ··· 172 170 } 173 171 } 174 172 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 173 impl Object for Label { 195 - fn call( 196 - self: &Arc<Self>, 197 - state: &State<'_, '_>, 174 + fn call_method( 175 + self: &Arc<Label>, 176 + _state: &State, 177 + name: &str, 198 178 _args: &[Value], 199 179 ) -> Result<Value, minijinja::Error> { 200 - self.view(state.env()).map(Value::from) 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 + } 201 190 } 202 191 } 203 192 204 - #[derive(Debug, serde::Serialize)] 193 + #[derive(Debug, serde::Serialize, serde::Deserialize)] 205 194 struct ApproximateLength { 206 195 rounded: u64, 207 196 }
-1
lx/src/templates/mod.rs
··· 1 - pub mod component; 2 1 mod filters; 3 2 mod functions; 4 3