diff options
Diffstat (limited to 'templates')
-rw-r--r-- | templates/Cargo.toml | 2 | ||||
-rw-r--r-- | templates/assets/style.css | 11 | ||||
-rw-r--r-- | templates/build.rs | 20 | ||||
-rw-r--r-- | templates/src/assets.rs | 47 | ||||
-rw-r--r-- | templates/src/lib.rs | 107 | ||||
-rw-r--r-- | templates/src/mf2.rs | 4 | ||||
-rw-r--r-- | templates/src/templates.rs | 3 |
7 files changed, 115 insertions, 79 deletions
diff --git a/templates/Cargo.toml b/templates/Cargo.toml index 19855e6..ca56dfe 100644 --- a/templates/Cargo.toml +++ b/templates/Cargo.toml @@ -28,5 +28,5 @@ serde_json = { workspace = true } version = "0.3.0" path = "../util" [dependencies.kittybox-indieauth] -version = "0.2.0" +version = "0.3.0" path = "../indieauth" diff --git a/templates/assets/style.css b/templates/assets/style.css index 6139288..97483d4 100644 --- a/templates/assets/style.css +++ b/templates/assets/style.css @@ -175,6 +175,7 @@ article.h-entry, article.h-feed, article.h-card, article.h-event { } .webinteractions > ul.counters > li > .icon { font-size: 1.5em; + font-family: emoji; } .webinteractions > ul.counters > li { display: inline-flex; @@ -300,11 +301,13 @@ body > a#skip-to-content:focus { white-space: nowrap; width: 1px; } - +/* Extras: styles to demarcate output generated by machine learning models + * (No, LLMs and diffusion image generation models are not artificial intelligence) + */ figure.llm-quote { background: #ddd; border-left: 0.5em solid black; - border-image: repeating-linear-gradient(45deg, #000000, #000000 0.75em, #FFFF00 0.75em, #FFFF00 1.5em) 8; + border-image: repeating-linear-gradient(45deg, #000000, #333333 0.75em, #DDDD00 0.75em, #FFFF00 1.5em) 8; padding: 0.5em; padding-left: 0.75em; margin-left: 3em; @@ -319,3 +322,7 @@ figure.llm-quote > figcaption { background-color: #242424; } } +img.diffusion-model-output { + border-left: 0.5em solid black; + border-image: repeating-linear-gradient(45deg, #000000, #333333 0.75em, #DDDD00 0.75em, #FFFF00 1.5em) 8; +} diff --git a/templates/build.rs b/templates/build.rs index 5a62855..057666b 100644 --- a/templates/build.rs +++ b/templates/build.rs @@ -22,8 +22,7 @@ fn main() -> Result<(), std::io::Error> { println!("cargo:rerun-if-changed=assets/"); let assets_path = std::path::Path::new("assets"); - let mut assets = WalkDir::new(assets_path) - .into_iter(); + let mut assets = WalkDir::new(assets_path).into_iter(); while let Some(Ok(entry)) = assets.next() { eprintln!("Processing {}", entry.path().display()); let out_path = out_dir.join(entry.path().strip_prefix(assets_path).unwrap()); @@ -31,11 +30,15 @@ fn main() -> Result<(), std::io::Error> { eprintln!("Creating directory {}", &out_path.display()); if let Err(err) = std::fs::create_dir(&out_path) { if err.kind() != std::io::ErrorKind::AlreadyExists { - return Err(err) + return Err(err); } } } else { - eprintln!("Copying {} to {}", entry.path().display(), out_path.display()); + eprintln!( + "Copying {} to {}", + entry.path().display(), + out_path.display() + ); std::fs::copy(entry.path(), &out_path)?; } } @@ -43,16 +46,11 @@ fn main() -> Result<(), std::io::Error> { let walker = WalkDir::new(&out_dir) .into_iter() .map(Result::unwrap) - .filter(|e| { - e.file_type().is_file() && e.path().extension().unwrap() != "gz" - }); + .filter(|e| e.file_type().is_file() && e.path().extension().unwrap() != "gz"); for entry in walker { let normal_path = entry.path(); let gzip_path = normal_path.with_extension({ - let mut extension = normal_path - .extension() - .unwrap() - .to_owned(); + let mut extension = normal_path.extension().unwrap().to_owned(); extension.push(OsStr::new(".gz")); extension }); diff --git a/templates/src/assets.rs b/templates/src/assets.rs new file mode 100644 index 0000000..493c14d --- /dev/null +++ b/templates/src/assets.rs @@ -0,0 +1,47 @@ +use axum::extract::Path; +use axum::http::header::{CACHE_CONTROL, CONTENT_ENCODING, CONTENT_TYPE, X_CONTENT_TYPE_OPTIONS}; +use axum::http::StatusCode; +use axum::response::{IntoResponse, Response}; + +const ASSETS: include_dir::Dir<'static> = include_dir::include_dir!("$OUT_DIR/"); +const CACHE_FOR_A_DAY: &str = "max-age=86400"; +const GZIP: &str = "gzip"; + +pub async fn statics(Path(path): Path<String>) -> Response { + let content_type: &'static str = if path.ends_with(".js") { + "application/javascript" + } else if path.ends_with(".css") { + "text/css" + } else if path.ends_with(".html") { + "text/html; charset=\"utf-8\"" + } else { + "application/octet-stream" + }; + + match ASSETS.get_file(path.clone() + ".gz") { + Some(file) => ( + StatusCode::OK, + [ + (CONTENT_TYPE, content_type), + (CONTENT_ENCODING, GZIP), + (CACHE_CONTROL, CACHE_FOR_A_DAY), + (X_CONTENT_TYPE_OPTIONS, "nosniff"), + ], + file.contents(), + ) + .into_response(), + None => match ASSETS.get_file(path) { + Some(file) => ( + StatusCode::OK, + [ + (CONTENT_TYPE, content_type), + (CACHE_CONTROL, CACHE_FOR_A_DAY), + (X_CONTENT_TYPE_OPTIONS, "nosniff"), + ], + file.contents(), + ) + .into_response(), + None => StatusCode::NOT_FOUND.into_response(), + }, + } +} diff --git a/templates/src/lib.rs b/templates/src/lib.rs index d9fe86b..0f9f7c6 100644 --- a/templates/src/lib.rs +++ b/templates/src/lib.rs @@ -7,55 +7,9 @@ pub use indieauth::AuthorizationRequestPage; mod login; pub use login::{LoginPage, LogoutPage}; mod mf2; -pub use mf2::{Entry, VCard, Feed, Food, POSTS_PER_PAGE}; - +pub use mf2::{Entry, Feed, Food, VCard, POSTS_PER_PAGE}; pub mod admin; - -pub mod assets { - use axum::response::{IntoResponse, Response}; - use axum::extract::Path; - use axum::http::StatusCode; - use axum::http::header::{CONTENT_TYPE, CONTENT_ENCODING, CACHE_CONTROL, X_CONTENT_TYPE_OPTIONS}; - - const ASSETS: include_dir::Dir<'static> = include_dir::include_dir!("$OUT_DIR/"); - const CACHE_FOR_A_DAY: &str = "max-age=86400"; - const GZIP: &str = "gzip"; - - pub async fn statics( - Path(path): Path<String> - ) -> Response { - let content_type: &'static str = if path.ends_with(".js") { - "application/javascript" - } else if path.ends_with(".css") { - "text/css" - } else if path.ends_with(".html") { - "text/html; charset=\"utf-8\"" - } else { - "application/octet-stream" - }; - - match ASSETS.get_file(path.clone() + ".gz") { - Some(file) => (StatusCode::OK, - [ - (CONTENT_TYPE, content_type), - (CONTENT_ENCODING, GZIP), - (CACHE_CONTROL, CACHE_FOR_A_DAY), - (X_CONTENT_TYPE_OPTIONS, "nosniff") - ], - file.contents()).into_response(), - None => match ASSETS.get_file(path) { - Some(file) => (StatusCode::OK, - [ - (CONTENT_TYPE, content_type), - (CACHE_CONTROL, CACHE_FOR_A_DAY), - (X_CONTENT_TYPE_OPTIONS, "nosniff") - ], - file.contents()).into_response(), - None => StatusCode::NOT_FOUND.into_response() - } - } - } -} +pub mod assets; #[cfg(test)] mod tests { @@ -107,11 +61,11 @@ mod tests { let dt = time::OffsetDateTime::now_utc() .to_offset( time::UtcOffset::from_hms( - rand::distributions::Uniform::new(-11, 12) - .sample(&mut rand::thread_rng()), + rand::distributions::Uniform::new(-11, 12).sample(&mut rand::thread_rng()), if rand::random::<bool>() { 0 } else { 30 }, - 0 - ).unwrap() + 0, + ) + .unwrap(), ) .format(&time::format_description::well_known::Rfc3339) .unwrap(); @@ -218,14 +172,15 @@ mod tests { // potentially with an offset? let offset = item.as_offset().unwrap().data; let date = item.as_date().unwrap().data; - let time = item.as_time().unwrap().data; + let time = item.as_time().unwrap().data; let dt = date.with_time(time).assume_offset(offset); let expected = time::OffsetDateTime::parse( mf2["properties"]["published"][0].as_str().unwrap(), - &time::format_description::well_known::Rfc3339 - ).unwrap(); - + &time::format_description::well_known::Rfc3339, + ) + .unwrap(); + assert_eq!(dt, expected); } else { unreachable!() @@ -235,7 +190,8 @@ mod tests { fn check_e_content(mf2: &serde_json::Value, item: &Item) { assert!(item.properties.contains_key("content")); - if let Some(PropertyValue::Fragment(content)) = item.properties.get("content").and_then(|v| v.first()) + if let Some(PropertyValue::Fragment(content)) = + item.properties.get("content").and_then(|v| v.first()) { assert_eq!( content.html, @@ -250,7 +206,11 @@ mod tests { fn test_note() { let mf2 = gen_random_post(&rand::random::<Domain>().to_string(), PostType::Note); - let html = crate::mf2::Entry { post: &mf2, from_feed: false, }.to_string(); + let html = crate::mf2::Entry { + post: &mf2, + from_feed: false, + } + .to_string(); let url: Url = mf2 .pointer("/properties/uid/0") @@ -259,7 +219,12 @@ mod tests { .unwrap(); let parsed: Document = microformats::from_html(&html, url.clone()).unwrap(); - if let Some(item) = parsed.into_iter().find(|i| i.properties.get("url").unwrap().contains(&PropertyValue::Url(url.clone()))) { + if let Some(item) = parsed.into_iter().find(|i| { + i.properties + .get("url") + .unwrap() + .contains(&PropertyValue::Url(url.clone())) + }) { let props = &item.properties; check_e_content(&mf2, &item); @@ -281,7 +246,11 @@ mod tests { #[test] fn test_article() { let mf2 = gen_random_post(&rand::random::<Domain>().to_string(), PostType::Article); - let html = crate::mf2::Entry { post: &mf2, from_feed: false, }.to_string(); + let html = crate::mf2::Entry { + post: &mf2, + from_feed: false, + } + .to_string(); let url: Url = mf2 .pointer("/properties/uid/0") .and_then(|i| i.as_str()) @@ -289,8 +258,12 @@ mod tests { .unwrap(); let parsed: Document = microformats::from_html(&html, url.clone()).unwrap(); - if let Some(item) = parsed.into_iter().find(|i| i.properties.get("url").unwrap().contains(&PropertyValue::Url(url.clone()))) { - + if let Some(item) = parsed.into_iter().find(|i| { + i.properties + .get("url") + .unwrap() + .contains(&PropertyValue::Url(url.clone())) + }) { check_e_content(&mf2, &item); check_dt_published(&mf2, &item); assert!(item.properties.contains_key("uid")); @@ -302,7 +275,9 @@ mod tests { .iter() .any(|i| i == item.properties.get("uid").and_then(|v| v.first()).unwrap())); assert!(item.properties.contains_key("name")); - if let Some(PropertyValue::Plain(name)) = item.properties.get("name").and_then(|v| v.first()) { + if let Some(PropertyValue::Plain(name)) = + item.properties.get("name").and_then(|v| v.first()) + { assert_eq!( name, mf2.pointer("/properties/name/0") @@ -338,7 +313,11 @@ mod tests { .and_then(|i| i.as_str()) .and_then(|u| u.parse().ok()) .unwrap(); - let html = crate::mf2::Entry { post: &mf2, from_feed: false, }.to_string(); + let html = crate::mf2::Entry { + post: &mf2, + from_feed: false, + } + .to_string(); let parsed: Document = microformats::from_html(&html, url.clone()).unwrap(); if let Some(item) = parsed.items.first() { diff --git a/templates/src/mf2.rs b/templates/src/mf2.rs index 787d3ed..aaac80f 100644 --- a/templates/src/mf2.rs +++ b/templates/src/mf2.rs @@ -1,3 +1,7 @@ +#![expect( + clippy::needless_lifetimes, + reason = "bug: Clippy doesn't realize the `markup` crate requires explicit lifetimes due to its idiosyncracies" +)] use ellipse::Ellipse; pub static POSTS_PER_PAGE: usize = 20; diff --git a/templates/src/templates.rs b/templates/src/templates.rs index 9b29fce..5772b4d 100644 --- a/templates/src/templates.rs +++ b/templates/src/templates.rs @@ -1,6 +1,7 @@ +#![allow(clippy::needless_lifetimes)] +use crate::{Feed, VCard}; use http::StatusCode; use kittybox_util::micropub::Channel; -use crate::{Feed, VCard}; markup::define! { Template<'a>(title: &'a str, blog_name: &'a str, feeds: Vec<Channel>, user: Option<&'a kittybox_indieauth::ProfileUrl>, content: String) { |