Homepage
This commit is contained in:
parent
de9291cd50
commit
1e772a97e2
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,68 @@
|
||||
{% extends "default" %}
|
||||
|
||||
{% block footer_vars %}
|
||||
{% set footer_links = false %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content -%}
|
||||
|
||||
<a href="{{ latest_post_permalink }}">
|
||||
{{ latest_post.metadata.title }}
|
||||
</a>
|
||||
<h2 class="headline">About Me</h2>
|
||||
<div class="body-content">
|
||||
<p class="about">
|
||||
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.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h2 class="headline">
|
||||
Latest Post:
|
||||
<a href="{{ latest_post_permalink }}">
|
||||
{{ latest_post.metadata.title }}
|
||||
</a>
|
||||
</h2>
|
||||
<p class="article-meta">
|
||||
Published on
|
||||
<time itemprop="datePublished" datetime="{{ latest_post.metadata.date | iso_datetime }}">
|
||||
{{ latest_post.metadata.date | pretty_date }},
|
||||
</time>
|
||||
in
|
||||
{% for tag in latest_post.metadata.tags %}
|
||||
<span itemprop="articleSection">
|
||||
<a href="/{{ tag.slug }}/">{{ tag.name }}</a>{% if loop.last %}.{% else %},{% endif %}
|
||||
</span>
|
||||
{% endfor %}
|
||||
{{ latest_post.word_count | reading_time }} minute read.
|
||||
</p>
|
||||
<div class="body-content">
|
||||
{% if latest_post.excerpt %}
|
||||
{{ latest_post.excerpt }}
|
||||
<p>
|
||||
<a href="{{ latest_post_permalink }}" class="read-more">Read more…</a>
|
||||
</p>
|
||||
{% else %}
|
||||
{{ latest_post_content }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<h2 class="headline">Other Things</h2>
|
||||
|
||||
{%- endblock %}
|
||||
|
||||
{% block footer_links %}
|
||||
{% set additional_links = [
|
||||
"Book Log", "/books/",
|
||||
"TV Commentary", "/tv/",
|
||||
"Modding Tutorials", "/tutorials/",
|
||||
] %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_footer_links %}
|
||||
<p class="webring">
|
||||
<a href="https://metro.bieszczady.pl">Metro Bieszczady Webring</a>
|
||||
<a title="previous page in webring" href="https://metro.bieszczady.pl/cgi-bin/webring?action=previous&from=shadowfacts">←</a>
|
||||
<a title="next page in webring" href="https://metro.bieszczady.pl/cgi-bin/webring?action=next&from=shadowfacts">→</a>
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
<article itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
|
||||
<meta itemprop="mainEntityOfPage" content="https://{{ _domain }}{{ _permalink }}">
|
||||
<h1 class="article-title" itemprop="name headline">
|
||||
<h1 class="headline" itemprop="name headline">
|
||||
{% if metadata.html_title %}
|
||||
{{ metadata.html_title }}
|
||||
{% else %}
|
||||
@ -51,7 +51,7 @@
|
||||
{% endfor %}
|
||||
{{ word_count | reading_time }} minute read.
|
||||
</p>
|
||||
<div class="article-content" itemprop="articleBody">
|
||||
<div class="body-content" itemprop="articleBody">
|
||||
{{ content }}
|
||||
</div>
|
||||
</article>
|
||||
|
@ -49,11 +49,22 @@
|
||||
<footer>
|
||||
<div class="container">
|
||||
<ul>
|
||||
<li><a href="/archive/">Archive</a></li>
|
||||
<li><a href="/elsewhere/">Contact</a></li>
|
||||
<!-- TODO: webring -->
|
||||
<li>Generated on {{ _generated_at | pretty_date }}, by <a href="https://git.shadowfacts.net/shadowfacts/v7">v7</a>.</li>
|
||||
{% set footer_links = [
|
||||
"Archive", "/archive/",
|
||||
"Colophon", "/colophon/",
|
||||
"Contact", "/elsewhere/"
|
||||
] %}
|
||||
{% block footer_links %}
|
||||
{% set additional_links = [] %}
|
||||
{% endblock %}
|
||||
{% set sorted_links = footer_links | concat(with=additional_links) | zip | sort(attribute="0") %}
|
||||
{% for link in sorted_links %}
|
||||
<li><a href="{{ link.1 }}">{{ link.0 }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% block after_footer_links %}
|
||||
{% endblock %}
|
||||
<p>Generated on {{ _generated_at | pretty_date }}, by <a href="https://git.shadowfacts.net/shadowfacts/v7">v7</a>.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
@ -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<ReadPostOutput>);
|
||||
impl Rule for ConvertToHTML {
|
||||
type Output = Option<Post<HtmlContent>>;
|
||||
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<Regex> = Lazy::new(|| Regex::new("<!--\\s*excerpt-end\\s*-->").unwrap());
|
||||
|
||||
fn find_excerpt(post: &Post<HtmlContent>) -> Option<String> {
|
||||
EXCERPT_REGEX
|
||||
.find(&post.content.html())
|
||||
.map(|m| post.content.html()[0..m.start()].trim().to_owned())
|
||||
}
|
||||
|
||||
// #[derive(InputVisitable)]
|
||||
// struct MakeExtractMetadatas {
|
||||
// posts: DynamicInput<ReadPostOutput>,
|
||||
|
@ -66,6 +66,10 @@ impl<C: PostContent> Post<C> {
|
||||
self.map_content(|c| c.to_html())
|
||||
}
|
||||
|
||||
pub fn with_excerpt(self, excerpt: Option<String>) -> Self {
|
||||
Post { excerpt, ..self }
|
||||
}
|
||||
|
||||
pub fn permalink(&self) -> String {
|
||||
format!("/{}/{}/", self.metadata.date.year(), self.slug)
|
||||
}
|
||||
|
@ -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<Tz>(datetime: &DateTime<Tz>) -> 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<String, Value>) -> Result<Value> {
|
||||
let date = DateTime::<Local>::deserialize(value)?;
|
||||
@ -256,9 +243,7 @@ pub mod filters {
|
||||
}
|
||||
|
||||
pub fn pretty_datetime(value: &Value, _args: &HashMap<String, Value>) -> Result<Value> {
|
||||
dbg!(value);
|
||||
let datetime = DateTime::<Local>::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<String, Value>) -> Result<Value> {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
@ -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};
|
||||
|
@ -1,25 +0,0 @@
|
||||
// static DOMAIN: Lazy<String> =
|
||||
// Lazy::new(|| std::env::var("DOMAIN").unwrap_or("shadowfacts.net".to_owned()));
|
||||
|
||||
// static CB: Lazy<u64> = Lazy::new(|| {
|
||||
// SystemTime::now()
|
||||
// .duration_since(SystemTime::UNIX_EPOCH)
|
||||
// .unwrap()
|
||||
// .as_secs()
|
||||
// });
|
||||
|
||||
// static GENERATED_AT: Lazy<DateTime<Local>> = Lazy::new(|| Local::now());
|
||||
|
||||
// pub trait TemplateCommon {
|
||||
// fn domain() -> String {
|
||||
// DOMAIN.to_owned()
|
||||
// }
|
||||
|
||||
// fn stylesheet_cache_buster() -> u64 {
|
||||
// *CB
|
||||
// }
|
||||
|
||||
// fn generated_at() -> &'static DateTime<Local> {
|
||||
// &*GENERATED_AT
|
||||
// }
|
||||
// }
|
Loading…
x
Reference in New Issue
Block a user