diff --git a/site_test/css/main.scss b/site_test/css/main.scss index 16ddd2d..7746e82 100644 --- a/site_test/css/main.scss +++ b/site_test/css/main.scss @@ -31,10 +31,6 @@ a:visited { color: var(--link-color); text-decoration-thickness: 2px; text-underline-offset: 2px; - /* color: white; - text-decoration: none; - background-color: black; - padding: 0 4px; */ } a:hover { text-decoration-thickness: 3px; @@ -159,7 +155,7 @@ header { } } -.article-title { +.headline { // balance the number of words per line text-wrap: balance; @@ -174,12 +170,16 @@ header { text-wrap: pretty; } -.article-content { +.body-content { font-size: 1.25rem; // Chrome only, but minimizes orphan words text-wrap: pretty; } +.read-more { + font-style: italic; +} + .header-anchor { text-decoration: none; font-size: 1rem; @@ -314,7 +314,7 @@ aside.inline { footer { margin-bottom: var(--page-vertical-margin); font-style: italic; - font-size: 1.5rem; + font-size: 1.25rem; ul { padding: 0; list-style: none; @@ -326,3 +326,23 @@ footer { font-size: 1rem; } } + +.webring { + background: linear-gradient( + 90deg, + #855988, + #6b4984, + #483475, + #2b2f77, + #141852 + ); + background-clip: text; + font-variant: small-caps; + font-weight: bold; + a { + color: transparent; + &::after { + display: none; + } + } +} diff --git a/site_test/index.html b/site_test/index.html index bc980a7..7e7e30b 100644 --- a/site_test/index.html +++ b/site_test/index.html @@ -1,9 +1,68 @@ {% extends "default" %} +{% block footer_vars %} +{% set footer_links = false %} +{% endblock %} + {% block content -%} - - {{ latest_post.metadata.title }} - +

About Me

+
+

+ Hi. + My day job is building software for people who pay me to build software. + In the evenings, I build software for people who don’t pay me to build software (myself included). + I mostly write about building software on here. + That probably doesn’t come as a shock. +

+
+ +

+ Latest Post: + + {{ latest_post.metadata.title }} + +

+

+ Published on + + in + {% for tag in latest_post.metadata.tags %} + + {{ tag.name }}{% if loop.last %}.{% else %},{% endif %} + + {% endfor %} + {{ latest_post.word_count | reading_time }} minute read. +

+
+ {% if latest_post.excerpt %} + {{ latest_post.excerpt }} +

+ Read more… +

+ {% else %} + {{ latest_post_content }} + {% endif %} +
+ +

Other Things

{%- endblock %} + +{% block footer_links %} +{% set additional_links = [ + "Book Log", "/books/", + "TV Commentary", "/tv/", + "Modding Tutorials", "/tutorials/", +] %} +{% endblock %} + +{% block after_footer_links %} +

+ Metro Bieszczady Webring + + +

+{% endblock %} diff --git a/site_test/layout/article.html b/site_test/layout/article.html index 563bff0..1ec17f1 100644 --- a/site_test/layout/article.html +++ b/site_test/layout/article.html @@ -31,7 +31,7 @@
-

+

{% if metadata.html_title %} {{ metadata.html_title }} {% else %} @@ -51,7 +51,7 @@ {% endfor %} {{ word_count | reading_time }} minute read.

-
+
{{ content }}

diff --git a/site_test/layout/default.html b/site_test/layout/default.html index ed0b8f9..b2e3088 100644 --- a/site_test/layout/default.html +++ b/site_test/layout/default.html @@ -49,11 +49,22 @@ diff --git a/src/generator/posts.rs b/src/generator/posts.rs index d3522be..46fde7e 100644 --- a/src/generator/posts.rs +++ b/src/generator/posts.rs @@ -14,6 +14,8 @@ use compute_graph::{ }; use content::{AnyContent, HtmlContent, Post, PostContent}; use log::error; +use once_cell::sync::Lazy; +use regex::Regex; use tera::Context; use super::{ @@ -192,10 +194,22 @@ struct ConvertToHTML(Input); impl Rule for ConvertToHTML { type Output = Option>; fn evaluate(&mut self) -> Self::Output { - self.input_0().clone().map(|post| post.to_html()) + self.input_0().clone().map(|post| { + let html_post = post.to_html(); + let excerpt = find_excerpt(&html_post); + html_post.with_excerpt(excerpt) + }) } } +static EXCERPT_REGEX: Lazy = Lazy::new(|| Regex::new("").unwrap()); + +fn find_excerpt(post: &Post) -> Option { + EXCERPT_REGEX + .find(&post.content.html()) + .map(|m| post.content.html()[0..m.start()].trim().to_owned()) +} + // #[derive(InputVisitable)] // struct MakeExtractMetadatas { // posts: DynamicInput, diff --git a/src/generator/posts/content.rs b/src/generator/posts/content.rs index 212868f..636517f 100644 --- a/src/generator/posts/content.rs +++ b/src/generator/posts/content.rs @@ -66,6 +66,10 @@ impl Post { self.map_content(|c| c.to_html()) } + pub fn with_excerpt(self, excerpt: Option) -> Self { + Post { excerpt, ..self } + } + pub fn permalink(&self) -> String { format!("/{}/{}/", self.metadata.date.year(), self.slug) } diff --git a/src/generator/templates.rs b/src/generator/templates.rs index 820def3..6ca1348 100644 --- a/src/generator/templates.rs +++ b/src/generator/templates.rs @@ -28,6 +28,7 @@ pub fn make_graph( empty_templates.register_filter("pretty_date", filters::pretty_date); empty_templates.register_filter("pretty_datetime", filters::pretty_datetime); empty_templates.register_filter("reading_time", filters::reading_time); + empty_templates.register_filter("zip", filters::zip); let empty_templates = builder.add_value(empty_templates); let default_path = content_path("layout/default.html"); @@ -214,21 +215,7 @@ pub mod filters { use chrono::{DateTime, Datelike, Local}; use serde::Deserialize; use std::collections::HashMap; - use tera::{Number, Result, Value}; - - // pub fn iso_date(date: &NaiveDate) -> String { - // Utc::from_utc_datetime(&Utc, &date.and_hms_opt(12, 0, 0).unwrap()) - // .format("%+:0") - // .to_string() - // } - - // pub fn iso_datetime(datetime: &DateTime) -> String - // where - // Tz: TimeZone, - // Tz::Offset: Display, - // { - // datetime.format("%+:0").to_string() - // } + use tera::{Error, Number, Result, Value}; pub fn iso_datetime(value: &Value, _args: &HashMap) -> Result { let date = DateTime::::deserialize(value)?; @@ -256,9 +243,7 @@ pub mod filters { } pub fn pretty_datetime(value: &Value, _args: &HashMap) -> Result { - dbg!(value); let datetime = DateTime::::deserialize(value)?; - dbg!(&datetime); let s = format!( "{} {}", datetime.format("%-I:%M:%S %p"), @@ -273,4 +258,22 @@ pub mod filters { let minutes = (words as f64 / wpm).max(1.0).round(); Ok(Value::Number(Number::from_f64(minutes).unwrap())) } + + pub fn zip(value: &Value, _args: &HashMap) -> Result { + let values = value + .as_array() + .ok_or_else(|| Error::msg("zip filter requires an array"))?; + if values.len() % 2 == 1 { + return Err(Error::msg("zipped array must have even length")); + } + let len = values.len() / 2; + let zipped = (0..len) + .map(|i| { + let first = values[i * 2].clone(); + let second = values[i * 2 + 1].clone(); + Value::Array(vec![first, second]) + }) + .collect(); + Ok(Value::Array(zipped)) + } } diff --git a/src/generator/util/mod.rs b/src/generator/util/mod.rs index 9178b95..348c821 100644 --- a/src/generator/util/mod.rs +++ b/src/generator/util/mod.rs @@ -2,7 +2,6 @@ pub mod file_watcher; pub mod highlight; pub mod one_more; pub mod slugify; -pub mod templates; pub mod word_count; use std::io::{BufWriter, Write}; diff --git a/src/generator/util/templates.rs b/src/generator/util/templates.rs deleted file mode 100644 index 7f39222..0000000 --- a/src/generator/util/templates.rs +++ /dev/null @@ -1,25 +0,0 @@ -// static DOMAIN: Lazy = -// Lazy::new(|| std::env::var("DOMAIN").unwrap_or("shadowfacts.net".to_owned())); - -// static CB: Lazy = Lazy::new(|| { -// SystemTime::now() -// .duration_since(SystemTime::UNIX_EPOCH) -// .unwrap() -// .as_secs() -// }); - -// static GENERATED_AT: Lazy> = Lazy::new(|| Local::now()); - -// pub trait TemplateCommon { -// fn domain() -> String { -// DOMAIN.to_owned() -// } - -// fn stylesheet_cache_buster() -> u64 { -// *CB -// } - -// fn generated_at() -> &'static DateTime { -// &*GENERATED_AT -// } -// }