Article metadata

This commit is contained in:
Shadowfacts 2025-01-12 16:08:06 -05:00
parent 3adf6031a4
commit f0ef67f9a0
4 changed files with 42 additions and 5 deletions

View File

@ -120,6 +120,15 @@ header {
.article-title { .article-title {
// balance the number of words per line // balance the number of words per line
text-wrap: balance; text-wrap: balance;
&:has(+ .article-meta) {
margin-bottom: 0.2em;
}
}
.article-meta {
margin-top: 0;
color: var(--secondary-text-color);
} }
.article-content { .article-content {

View File

@ -38,6 +38,19 @@
{{ metadata.title }} {{ metadata.title }}
{% endif %} {% endif %}
</h1> </h1>
<p class="article-meta">
Published on
<time itemprop="datePublished" datetime="{{ metadata.date | iso_datetime }}">
{{ metadata.date | pretty_date }},
</time>
in
{% for tag in metadata.tags %}
<span itemprop="articleSection">
<a href="/{{ tag.slug }}/">{{ tag.name }}</a>{% if loop.last %}.{% else %},{% endif %}
</span>
{% endfor %}
{{ word_count | reading_time }} minute read.
</p>
<div class="article-content" itemprop="articleBody"> <div class="article-content" itemprop="articleBody">
{{ content }} {{ content }}
</div> </div>

View File

@ -284,6 +284,12 @@ impl DynamicRule for MakeWritePosts {
|post_opt, ctx| { |post_opt, ctx| {
let post = post_opt.as_ref().unwrap(); let post = post_opt.as_ref().unwrap();
ctx.insert("metadata", &post.metadata); ctx.insert("metadata", &post.metadata);
ctx.insert(
"word_count",
&post
.word_count
.expect("post should have word count when rendering"),
);
ctx.insert("content", post.content.html()); ctx.insert("content", post.content.html());
}, },
)) ))

View File

@ -24,8 +24,10 @@ pub fn make_graph(
watcher: &mut FileWatcher, watcher: &mut FileWatcher,
) -> Input<Templates> { ) -> Input<Templates> {
let mut empty_templates = Templates::default(); let mut empty_templates = Templates::default();
empty_templates.register_filter("iso_datetime", filters::iso_datetime);
empty_templates.register_filter("pretty_date", filters::pretty_date); empty_templates.register_filter("pretty_date", filters::pretty_date);
empty_templates.register_filter("pretty_datetime", filters::pretty_datetime); empty_templates.register_filter("pretty_datetime", filters::pretty_datetime);
empty_templates.register_filter("reading_time", filters::reading_time);
let empty_templates = builder.add_value(empty_templates); let empty_templates = builder.add_value(empty_templates);
let default_path = content_path("layout/default.html"); let default_path = content_path("layout/default.html");
@ -212,7 +214,7 @@ pub mod filters {
use chrono::{DateTime, Datelike, Local}; use chrono::{DateTime, Datelike, Local};
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashMap; use std::collections::HashMap;
use tera::{Result, Value}; use tera::{Number, Result, Value};
// pub fn iso_date(date: &NaiveDate) -> String { // pub fn iso_date(date: &NaiveDate) -> String {
// Utc::from_utc_datetime(&Utc, &date.and_hms_opt(12, 0, 0).unwrap()) // Utc::from_utc_datetime(&Utc, &date.and_hms_opt(12, 0, 0).unwrap())
@ -228,6 +230,11 @@ pub mod filters {
// datetime.format("%+:0").to_string() // datetime.format("%+:0").to_string()
// } // }
pub fn iso_datetime(value: &Value, _args: &HashMap<String, Value>) -> Result<Value> {
let date = DateTime::<Local>::deserialize(value)?;
Ok(Value::String(date.format("%+:0").to_string()))
}
const MONTHS: &[&str; 12] = &[ const MONTHS: &[&str; 12] = &[
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
]; ];
@ -260,8 +267,10 @@ pub mod filters {
Ok(Value::String(s)) Ok(Value::String(s))
} }
// pub fn reading_time(words: &u32) -> u32 { pub fn reading_time(value: &Value, _args: &HashMap<String, Value>) -> Result<Value> {
// let wpm = 225.0; let words = u32::deserialize(value)?;
// (*words as f32 / wpm).max(1.0) as u32 let wpm = 225.0;
// } let minutes = (words as f64 / wpm).max(1.0).round();
Ok(Value::Number(Number::from_f64(minutes).unwrap()))
}
} }