chug chug, working on post formatting and tag pages
This commit is contained in:
19
_config/filters.js
Normal file
19
_config/filters.js
Normal 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);
|
||||||
|
});
|
||||||
|
};
|
||||||
@ -26,3 +26,4 @@
|
|||||||
<link rel="stylesheet" href="/assets/css/highlighting.css">
|
<link rel="stylesheet" href="/assets/css/highlighting.css">
|
||||||
<link rel="stylesheet" href="/assets/css/print.css">
|
<link rel="stylesheet" href="/assets/css/print.css">
|
||||||
<link rel="stylesheet" href="/assets/css/postlist.css">
|
<link rel="stylesheet" href="/assets/css/postlist.css">
|
||||||
|
<link rel="stylesheet" href="/assets/css/post.css">
|
||||||
|
|||||||
@ -4,5 +4,28 @@ layout: base.njk
|
|||||||
<article>
|
<article>
|
||||||
<h1>{{ title }}</h1>
|
<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 }}
|
{{ content | safe }}
|
||||||
</article>
|
</article>
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<img src="/img/{{ post.data.image.src }}" alt="{{ post.data.image.alt }}">
|
<img src="/img/{{ post.data.image.src }}" alt="{{ post.data.image.alt }}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<h2>{{ post.data.title }}</h2>
|
<h2>{{ post.data.title }}</h2>
|
||||||
<ul class="posttags">
|
<ul class="postlist-tags">
|
||||||
{% for tag in post.data.tags | removeBasicTags %}
|
{% for tag in post.data.tags | removeBasicTags %}
|
||||||
<li>{{ tag }}</li>
|
<li>{{ tag }}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@ -69,11 +69,17 @@ body {
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
width: 60vw;
|
width: 60vw;
|
||||||
max-width: 1200px;
|
max-width: 1000px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
scroll-margin-top: var(--header-offset);
|
scroll-margin-top: var(--header-offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1050px) {
|
||||||
|
main {
|
||||||
|
width: 75vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 650px) {
|
@media (max-width: 650px) {
|
||||||
main {
|
main {
|
||||||
width: 92vw;
|
width: 92vw;
|
||||||
|
|||||||
@ -18,7 +18,7 @@ header a {
|
|||||||
box-shadow: .15rem .15rem var(--color-shadow);
|
box-shadow: .15rem .15rem var(--color-shadow);
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
padding-right: .35rem;
|
padding-right: .35rem;
|
||||||
/* click animation handling */
|
/* Click animation handling */
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
@ -133,6 +133,11 @@ header ul {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header ul,
|
||||||
|
header li {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 650px) {
|
@media (max-width: 650px) {
|
||||||
.menu-text {
|
.menu-text {
|
||||||
display: none; /* Icons only on small screens */
|
display: none; /* Icons only on small screens */
|
||||||
|
|||||||
75
css/post.css
Normal file
75
css/post.css
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@
|
|||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-color: var(--color-primary);
|
border-color: var(--color-primary);
|
||||||
/* click animation handline */
|
/* Click animation handling */
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
@ -98,7 +98,7 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* h2 */
|
/* Headers */
|
||||||
.post h2 {
|
.post h2 {
|
||||||
grid-area: h2;
|
grid-area: h2;
|
||||||
padding: .25rem .5rem;
|
padding: .25rem .5rem;
|
||||||
@ -131,7 +131,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Tags */
|
/* Tags */
|
||||||
.posttags {
|
.postlist-tags {
|
||||||
grid-area: tags;
|
grid-area: tags;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -140,28 +140,28 @@
|
|||||||
padding: .5rem;
|
padding: .5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post:nth-child(odd) .posttags {
|
.post:nth-child(odd) .postlist-tags {
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post:nth-child(odd) .posttags {
|
.post:nth-child(odd) .postlist-tags {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.posttags li {
|
.postlist-tags li {
|
||||||
background-color: var(--color-primary);
|
background-color: var(--color-primary);
|
||||||
color: var(--color-bg);
|
color: var(--color-bg);
|
||||||
padding: 0 .5rem;
|
padding: 0 .5rem;
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.postlink:focus-visible .posttags li {
|
.postlink:focus-visible .postlist-tags li {
|
||||||
background-color: var(--color-bg);
|
background-color: var(--color-bg);
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (any-hover: hover) {
|
@media (any-hover: hover) {
|
||||||
.postlink:hover .posttags li {
|
.postlink:hover .postlist-tags li {
|
||||||
background-color: var(--color-bg);
|
background-color: var(--color-bg);
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,20 +3,46 @@ import eleventyNavigationPlugin from "@11ty/eleventy-navigation";
|
|||||||
import { feedPlugin } from "@11ty/eleventy-plugin-rss";
|
import { feedPlugin } from "@11ty/eleventy-plugin-rss";
|
||||||
import syntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
|
import syntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
|
||||||
import { attrs } from "@mdit/plugin-attrs";
|
import { attrs } from "@mdit/plugin-attrs";
|
||||||
|
import { chunk } from "lodash-es";
|
||||||
|
|
||||||
|
import pluginFilters from "./_config/filters.js";
|
||||||
|
|
||||||
export default async function(eleventyConfig) {
|
export default async function(eleventyConfig) {
|
||||||
/* Markdown HTML attribute parsing */
|
/* Markdown HTML attribute parsing */
|
||||||
eleventyConfig.amendLibrary("md", (mdLib) => mdLib.use(attrs));
|
eleventyConfig.amendLibrary("md", (mdLib) => mdLib.use(attrs));
|
||||||
|
|
||||||
/* Filters */
|
/* Collections */
|
||||||
eleventyConfig.addFilter("removeBasicTags", (tags) => {
|
/* Tag pagination */
|
||||||
return tags.filter(tag => ["all", "posts", "gallery", "reference"].indexOf(tag) === -1);
|
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 */
|
/* Passthroughs */
|
||||||
eleventyConfig.addPassthroughCopy({"css": "assets/css"});
|
eleventyConfig.addPassthroughCopy({"css": "assets/css"});
|
||||||
|
|
||||||
/* Plugins */
|
/* Plugins */
|
||||||
|
/* All filters from _config/filters.js */
|
||||||
|
eleventyConfig.addPlugin(pluginFilters);
|
||||||
|
|
||||||
/* RSS */
|
/* RSS */
|
||||||
eleventyConfig.addPlugin(feedPlugin, {
|
eleventyConfig.addPlugin(feedPlugin, {
|
||||||
type: "atom", // or "rss", "json"
|
type: "atom", // or "rss", "json"
|
||||||
@ -43,7 +69,7 @@ export default async function(eleventyConfig) {
|
|||||||
formats: ["auto"],
|
formats: ["auto"],
|
||||||
|
|
||||||
// output image widths
|
// output image widths
|
||||||
widths: [800],
|
widths: [1000],
|
||||||
|
|
||||||
// optional, attributes assigned on <img> nodes override these values
|
// optional, attributes assigned on <img> nodes override these values
|
||||||
htmlOptions: {
|
htmlOptions: {
|
||||||
|
|||||||
11
package-lock.json
generated
11
package-lock.json
generated
@ -14,7 +14,9 @@
|
|||||||
"@11ty/eleventy-navigation": "^1.0.5",
|
"@11ty/eleventy-navigation": "^1.0.5",
|
||||||
"@11ty/eleventy-plugin-rss": "^2.0.4",
|
"@11ty/eleventy-plugin-rss": "^2.0.4",
|
||||||
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.2",
|
"@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": {
|
"node_modules/@11ty/dependency-tree": {
|
||||||
@ -1794,6 +1796,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/luxon": {
|
||||||
"version": "3.7.2",
|
"version": "3.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz",
|
||||||
|
|||||||
@ -16,6 +16,8 @@
|
|||||||
"@11ty/eleventy-navigation": "^1.0.5",
|
"@11ty/eleventy-navigation": "^1.0.5",
|
||||||
"@11ty/eleventy-plugin-rss": "^2.0.4",
|
"@11ty/eleventy-plugin-rss": "^2.0.4",
|
||||||
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.2",
|
"@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
9
src/meta/404.md
Normal 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
16
src/meta/sitemap.xml
Normal 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>
|
||||||
@ -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).
|
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).
|
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
24
src/pages/tag-pages.njk
Normal 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 %}
|
||||||
@ -2,8 +2,6 @@
|
|||||||
title: Sample
|
title: Sample
|
||||||
date: 2026-02-17
|
date: 2026-02-17
|
||||||
tags:
|
tags:
|
||||||
- some
|
|
||||||
- tags
|
|
||||||
- gallery
|
- gallery
|
||||||
image:
|
image:
|
||||||
src: 2026/sample-0.jpg
|
src: 2026/sample-0.jpg
|
||||||
|
|||||||
Reference in New Issue
Block a user