chug chug, working on post formatting and tag pages

This commit is contained in:
2026-02-18 18:44:17 -08:00
parent ca8d4a31cd
commit f2face01a7
17 changed files with 234 additions and 19 deletions

19
_config/filters.js Normal file
View File

@ -0,0 +1,19 @@
import { DateTime } from "luxon";
export default function(eleventyConfig) {
/* Human-readable dates */
eleventyConfig.addFilter("readableDate", (dateObj, format, zone) => {
return DateTime.fromJSDate(dateObj, { zone: zone || "utc" })
.toLocaleString(DateTime.DATE_FULL);
});
/* For <time> elements */
eleventyConfig.addFilter("htmlDateString", (dateObj) => {
return DateTime.fromJSDate(dateObj, { zone: "utc" }).toFormat('yyyy-LL-dd');
});
/* Filter out structural tags */
eleventyConfig.addFilter("removeBasicTags", (tags) => {
return tags.filter(tag => ["all", "posts", "gallery", "reference", "tagPagination"].indexOf(tag) === -1);
});
};

View File

@ -26,3 +26,4 @@
<link rel="stylesheet" href="/assets/css/highlighting.css">
<link rel="stylesheet" href="/assets/css/print.css">
<link rel="stylesheet" href="/assets/css/postlist.css">
<link rel="stylesheet" href="/assets/css/post.css">

View File

@ -4,5 +4,28 @@ layout: base.njk
<article>
<h1>{{ title }}</h1>
<div class="post-metadata">
<p>
posted on
<time datetime="{{ page.date | htmlDateString }}">{{ page.date | readableDate }}</time>
by {{ metadata.author }}
</p>
{% set relevantTags = tags | removeBasicTags %}
{% if relevantTags.length %}
<ul class="post-tags">
{% for tag in relevantTags %}
<li>
{% set tagUrl %}/tag/{{ tag | slugify }}/{% endset %}
<a href="{{ tagUrl }}">{{ tag }}</a>
</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% if image %}
<img src="/img/{{ image.src }}" alt="{{ image.alt }}">
{% endif %}
{{ content | safe }}
</article>

View File

@ -6,7 +6,7 @@
<img src="/img/{{ post.data.image.src }}" alt="{{ post.data.image.alt }}">
{% endif %}
<h2>{{ post.data.title }}</h2>
<ul class="posttags">
<ul class="postlist-tags">
{% for tag in post.data.tags | removeBasicTags %}
<li>{{ tag }}</li>
{% endfor %}

View File

@ -69,11 +69,17 @@ body {
main {
width: 60vw;
max-width: 1200px;
max-width: 1000px;
margin: 0 auto;
scroll-margin-top: var(--header-offset);
}
@media (max-width: 1050px) {
main {
width: 75vw;
}
}
@media (max-width: 650px) {
main {
width: 92vw;

View File

@ -18,7 +18,7 @@ header a {
box-shadow: .15rem .15rem var(--color-shadow);
font-size: 1.2rem;
padding-right: .35rem;
/* click animation handling */
/* Click animation handling */
position: relative;
top: 0;
left: 0;
@ -133,6 +133,11 @@ header ul {
justify-content: center;
}
header ul,
header li {
margin: 0;
}
@media (max-width: 650px) {
.menu-text {
display: none; /* Icons only on small screens */

75
css/post.css Normal file
View File

@ -0,0 +1,75 @@
.post-metadata {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
align-items: baseline;
margin: 1.5rem 0 .5rem;
}
.post-metadata p {
font-size: .9rem;
margin: 0;
}
.post-tags {
display: flex;
flex-flow: row wrap;
gap: .5rem;
list-style: none;
margin: 0;
}
.post-tags li {
margin: 0;
}
.post-tags li a {
text-decoration: none;
color: var(--color-teal);
padding: 0 .5rem;
border-radius: 1rem;
box-shadow: .15rem .15rem var(--color-shadow);
border: .08rem solid var(--color-teal);
line-height: 2;
/* Click animation handling */
position: relative;
top: 0;
left: 0;
transition: top .1s ease-in, left .1s ease-in;
}
.post-tags li a:focus-visible {
outline: none;
background-color: var(--color-teal);
color: var(--color-bg);
}
@media (any-hover: hover) {
.post-tags li a:hover {
outline: none;
background-color: var(--color-teal);
color: var(--color-bg);
}
}
@media (forced-colors: active) {
.post-tags li a:focus-visible {
outline-offset: .08rem;
outline: .08rem solid;
}
@media (any-hover: hover) {
.post-tags li a:hover {
outline-offset: .08rem;
outline: .08rem solid;
}
}
}
/* Click animation */
.post-tags li a:active {
top: .1rem;
left: .1rem;
box-shadow: .05rem .05rem var(--color-shadow);
}

View File

@ -49,7 +49,7 @@
margin: 2rem 0;
text-decoration: none;
border-color: var(--color-primary);
/* click animation handline */
/* Click animation handling */
position: relative;
top: 0;
left: 0;
@ -98,7 +98,7 @@
margin: 0;
}
/* h2 */
/* Headers */
.post h2 {
grid-area: h2;
padding: .25rem .5rem;
@ -131,7 +131,7 @@
}
/* Tags */
.posttags {
.postlist-tags {
grid-area: tags;
list-style: none;
display: flex;
@ -140,28 +140,28 @@
padding: .5rem;
}
.post:nth-child(odd) .posttags {
.post:nth-child(odd) .postlist-tags {
justify-content: flex-end;
}
.post:nth-child(odd) .posttags {
.post:nth-child(odd) .postlist-tags {
justify-content: flex-start;
}
.posttags li {
.postlist-tags li {
background-color: var(--color-primary);
color: var(--color-bg);
padding: 0 .5rem;
border-radius: 1rem;
}
.postlink:focus-visible .posttags li {
.postlink:focus-visible .postlist-tags li {
background-color: var(--color-bg);
color: var(--color-primary);
}
@media (any-hover: hover) {
.postlink:hover .posttags li {
.postlink:hover .postlist-tags li {
background-color: var(--color-bg);
color: var(--color-primary);
}

View File

@ -3,20 +3,46 @@ import eleventyNavigationPlugin from "@11ty/eleventy-navigation";
import { feedPlugin } from "@11ty/eleventy-plugin-rss";
import syntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
import { attrs } from "@mdit/plugin-attrs";
import { chunk } from "lodash-es";
import pluginFilters from "./_config/filters.js";
export default async function(eleventyConfig) {
/* Markdown HTML attribute parsing */
eleventyConfig.amendLibrary("md", (mdLib) => mdLib.use(attrs));
/* Filters */
eleventyConfig.addFilter("removeBasicTags", (tags) => {
return tags.filter(tag => ["all", "posts", "gallery", "reference"].indexOf(tag) === -1);
/* Collections */
/* Tag pagination */
eleventyConfig.addCollection("tagPagination", function(collection) {
let tagSet = new Set(collection.getAllSorted().flatMap((post) => post.data.tags || []));
let paginationSize = 13;
let tagMap = [];
let tagArray = [...tagSet];
for( let tagName of tagArray) {
let tagItems = collection.getFilteredByTag(tagName);
let pagedItems = chunk(tagItems.reverse(), paginationSize); // console.log( tagName, tagItems.length, pagedItems.length );
for( let pageNumber = 0, max = pagedItems.length; pageNumber < max; pageNumber++) {
tagMap.push({
tagName: tagName,
pageNumber: pageNumber,
pageSize: pagedItems.length,
pageData: pagedItems[pageNumber]
});
}
}
//console.log( tagMap );
return tagMap;
});
/* Passthroughs */
eleventyConfig.addPassthroughCopy({"css": "assets/css"});
/* Plugins */
/* All filters from _config/filters.js */
eleventyConfig.addPlugin(pluginFilters);
/* RSS */
eleventyConfig.addPlugin(feedPlugin, {
type: "atom", // or "rss", "json"
@ -43,7 +69,7 @@ export default async function(eleventyConfig) {
formats: ["auto"],
// output image widths
widths: [800],
widths: [1000],
// optional, attributes assigned on <img> nodes override these values
htmlOptions: {

11
package-lock.json generated
View File

@ -14,7 +14,9 @@
"@11ty/eleventy-navigation": "^1.0.5",
"@11ty/eleventy-plugin-rss": "^2.0.4",
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.2",
"@mdit/plugin-attrs": "^0.24.2"
"@mdit/plugin-attrs": "^0.24.2",
"lodash-es": "^4.17.23",
"luxon": "^3.7.2"
}
},
"node_modules/@11ty/dependency-tree": {
@ -1794,6 +1796,13 @@
"dev": true,
"license": "MIT"
},
"node_modules/lodash-es": {
"version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz",
"integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==",
"dev": true,
"license": "MIT"
},
"node_modules/luxon": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz",

View File

@ -16,6 +16,8 @@
"@11ty/eleventy-navigation": "^1.0.5",
"@11ty/eleventy-plugin-rss": "^2.0.4",
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.2",
"@mdit/plugin-attrs": "^0.24.2"
"@mdit/plugin-attrs": "^0.24.2",
"lodash-es": "^4.17.23",
"luxon": "^3.7.2"
}
}

9
src/meta/404.md Normal file
View File

@ -0,0 +1,9 @@
---
layout: page.njk
permalink: 404.html
eleventyExcludeFromCollections: true
---
# Sorry, can't find that
Head [home](/).

16
src/meta/sitemap.xml Normal file
View File

@ -0,0 +1,16 @@
---
permalink: sitemap.xml
eleventyExcludeFromCollections: true
---
<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">
{% for page in collections.all %}
{% if page.data.permalink != false %}
{% set absoluteUrl %}{{ page.url | htmlBaseUrl(metadata.url) }}{% endset %}
<url>
<loc>{{ absoluteUrl }}</loc>
<lastmod>{{ page.date | htmlDateString }}</lastmod>
</url>
{% endif %}
{% endfor %}
</urlset>

View File

@ -17,3 +17,5 @@ This site is created [without the use of generative AI](https://declare-ai.org/1
You can [find the accessibility statement for leecat.art here](/accessibility).
If you'd like, you can view the [site palette](/palette) or the [style overview](/style).
[The sitemap can be found here](/sitemap.xml).

24
src/pages/tag-pages.njk Normal file
View File

@ -0,0 +1,24 @@
---
pagination:
data: collections.doublePagination
size: 1
alias: tag
eleventyComputed:
permalink: /tag/{{ tag.tagName | slugify }}/{% if tag.pageNumber %}{{ tag.pageNumber + 1 }}/{% endif %}
title: "Posts tagged {{ tag.tagName }}"
---
{% set postlist = tag.pageData %}
{% include "postlist.njk" %}
{% if tag.pageNumber > 0 or tag.pageNumber < tag.pageSize - 1 %}
<nav aria-label="pagination">
<ol class="pagination">
{% if tag.pageNumber > 0 %}
<li class="prev"><a href="{{ pagination.href.previous }}"><< Previous</a></li>
{% endif %}
{% if tag.pageNumber < tag.pageSize - 1 %}
<li class="next"><a href="{{ pagination.href.next }}">Next >></a></li>
{% endif %}
</ol>
</nav>
{% endif %}

View File

@ -2,8 +2,6 @@
title: Sample
date: 2026-02-17
tags:
- some
- tags
- gallery
image:
src: 2026/sample-0.jpg