sigh - convert everything to Liquid templates (instead of Pug) since it is first-class supported in Eleventy

This commit is contained in:
2026-03-23 21:46:35 -05:00
parent 75dc13f8da
commit c25e2ac380
42 changed files with 452 additions and 392 deletions

View File

@@ -29,6 +29,10 @@ const setupPlugins = eleventyConfig => {
},
},
})
eleventyConfig.addLiquidFilter('dateToRfc822', rssPlugin.dateToRfc822)
eleventyConfig.addLiquidFilter('dateToRfc3339', rssPlugin.dateToRfc3339)
eleventyConfig.addLiquidFilter('getNewestCollectionItemDate', rssPlugin.getNewestCollectionItemDate)
}
export default function (eleventyConfig) {

21
src/_includes/blog.liquid Normal file
View File

@@ -0,0 +1,21 @@
{% layout 'obsidian.liquid' %}
{% block content %}
<div class="container" id="top">
<div class="inner">
<section id="blog-header">
<h1>Garrett's Blog</h1>
<p class="button-links">
<a class="button" href="/blog">Home</a>
<a class="button" href="/blog/archive">Archive</a>
<a class="button" href="/blog/tags">Tags</a>
<a class="button" href="/blog/feeds">Feeds</a>
</p>
</section>
{% block blog_content %}
<div class="content-wrapper">{{ content }}</div>
{% endblock %}
</div>
</div>
{% endblock %}

View File

@@ -1,15 +0,0 @@
extends ./obsidian
block content
.container#top
.inner
section#blog-header
h1 Garrett's Blog
p.button-links
a.button(href='/blog') Home
a.button(href='/blog/archive') Archive
a.button(href='/blog/tags') Tags
a.button(href='/blog/feeds') Feeds
block blog_content
.content-wrapper !{content}

View File

@@ -0,0 +1,16 @@
{% layout 'blog.liquid' %}
{% block blog_content %}
<h2>{{ title }}</h2>
<p>by Garrett Mills on {{ page.date | date: "%Y-%m-%d" }}</p>
<div class="post-tags">
<p class="button-links">
{% for tag in blogtags %}
<a class="button-small secondary" href="/blog/tag/{{ tag }}">#{{ tag }}</a>
{% endfor %}
</p>
</div>
{% block blog_inner_content %}
<div class="blog content-wrapper">{{ content }}</div>
{% endblock %}
{% endblock %}

View File

@@ -1,10 +0,0 @@
extends ./blog
block blog_content
h2 #{title}
p by Garrett Mills on #{page.date.toISOString().split('T')[0]}
.post-tags
p.button-links
each tag in blogtags
a.button-small.secondary(href='/blog/tag/' + tag) ##{tag}
.blog.content-wrapper !{content}

View File

@@ -0,0 +1,20 @@
{% layout 'obsidian.liquid' %}
{% block content %}
<div class="feed">
<div class="post" id="{{ slug }}">
{% if feedtags %}
<div class="tags">
{% for tag in feedtags %}
<a class="tag" href="#">{{ tag }}</a>
{% endfor %}
</div>
{% endif %}
<h2>{{ title }}</h2>
<div class="content-wrapper">{{ content }}</div>
<div class="footer">
<span class="date">{{ date | date: "%m/%d/%Y" }}</span>
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,13 +0,0 @@
extends ./obsidian
block content
.feed
.post(id=slug)
if feedtags
.tags
each tag in feedtags
a.tag(href="#") #{tag}
h2 #{title}
.content-wrapper !{content}
.footer
span.date #{date.toLocaleDateString()}

View File

@@ -0,0 +1,7 @@
{% layout 'obsidian.liquid' %}
{% block content %}
<img src="/assets/markmark-light.svg" eleventy:ignore>
<header class="hero-2">Standard MarkMark (v1.1)</header>
<div class="markmark content-wrapper">{{ content }}</div>
{% endblock %}

View File

@@ -1,6 +0,0 @@
extends ./obsidian
block content
img(src='/assets/markmark-light.svg' eleventy:ignore)
header.hero-2 Standard MarkMark (v1.1)
.markmark.content-wrapper !{content}

View File

@@ -0,0 +1,130 @@
<!DOCTYPE html>
<html lang="en">
<head>
<style>
body {
--background: #111;
--background-2: #252525;
--background-3: #444;
--color: #fffbe3;
--color-2: #d0c895;
background: var(--background);
color: var(--color);
font-family: "Reckless", serif;
margin: 0;
padding: 0;
overflow-x: hidden;
display: flex;
flex-direction: column;
align-items: center;
}
.wrapper {
max-width: 800px;
width: calc(100% - 40px);
padding-left: 20px;
padding-right: 20px;
margin-bottom: 100px;
min-height: 100vh;
}
</style>
{% block meta %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="description" content="Hi, there! My name is Garrett. I am a computer scientist, software engineer, and speaker.">
<meta name="keywords" content="garrett mills glmdev developer speaker flitter extollo student">
<meta name="author" content="Garrett Mills">
<meta name="robots" content="index, follow">
<link rel="author" href="/humans.txt">
<link rel="alternate" href="/feed/atom.xml" title="Garrett Mills - Notes (Atom)" type="application/atom+xml">
<link rel="alternate" href="/feed/rss.xml" title="Garrett Mills - Notes (RSS)" type="application/rss+xml">
<link rel="alternate" href="/feed/json.json" title="Garrett Mills - Notes (JSON)" type="application/feed+json">
<link rel="alternate" href="/blog/atom.xml" title="Garrett's Blog (Atom)" type="application/atom+xml">
<link rel="alternate" href="/blog/rss2.xml" title="Garrett's Blog (RSS)" type="application/rss+xml">
<link rel="alternate" href="/blog/json.json" title="Garrett's Blog (JSON)" type="application/feed+json">
{% include 'meta.html' %}
{% endblock %}
{% block title %}
{% if title %}
<title>{{ title }} | Garrett Mills</title>
{% else %}
<title>Garrett Mills</title>
{% endif %}
{% endblock %}
{% block style %}
<!-- Register fonts here to avoid 2 layer network dependency tree for bundle.css -->
<style>
@font-face {
font-family: 'Obsidian';
src: url('/assets/font/obsidian/Obsidian-Roman.otf') format('opentype');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "JetBrains Mono";
src: url("/assets/font/jetbrains-mono/JetBrainsMono-Regular.woff2") format('woff2');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Reckless";
src: url("/assets/font/reckless/WEB/Reckless-Regular.woff2") format('woff2');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Reckless";
src: url("/assets/font/reckless/WEB/Reckless-RegularItalic.woff2") format('woff2');
font-weight: normal;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: "Reckless";
src: url("/assets/font/reckless/WEB/Reckless-Bold.woff2") format('woff2');
font-weight: bold;
font-style: normal;
font-display: swap;
}
</style>
<link rel="stylesheet" href="/bundle.css">
{% endblock %}
</head>
<body>
<div class="wrapper">
<header class="hero">glm.</header>
<nav>
<ul>
<li><a href="/">Home</a></li>
<!--<li><a href="/timeline">Timeline</a></li>-->
<li><a href="/blog">Blog</a></li>
<li><a href="/feed">Notes</a></li>
<li><a href="/links">Bookmarks <img class="inline-markmark-logo" src="/assets/img/markmark-light.svg" eleventy:ignore alt="MarkMark logo"/></a></li>
</ul>
</nav>
{% block content %}
<div class="content-wrapper" role="main">{{ content }}</div>
{% endblock %}
</div>
<footer>
<div class="obsidian">glm.</div>
<p>&copy; 2015-{{ "now" | date: "%Y" }} Garrett Mills — <a href="/technical">Technical Info</a><br><small><a href="/technical/#source-code-and-licensing">AI Scraping Notice</a></small></p>
</footer>
{% block script %}{% endblock %}
</body>
</html>

View File

@@ -1,124 +0,0 @@
doctype html
html(lang="en")
head
style.
body {
--background: #111;
--background-2: #252525;
--background-3: #444;
--color: #fffbe3;
--color-2: #d0c895;
background: var(--background);
color: var(--color);
font-family: "Reckless", serif;
margin: 0;
padding: 0;
overflow-x: hidden;
display: flex;
flex-direction: column;
align-items: center;
}
.wrapper {
max-width: 800px;
width: calc(100% - 40px);
padding-left: 20px;
padding-right: 20px;
margin-bottom: 100px;
min-height: 100vh;
}
block meta
meta(charset='utf-8')
meta(name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no')
meta(http-equiv='x-ua-compatible' content='ie=edge')
meta(name='description' content='Hi, there! My name is Garrett. I am a computer scientist, software engineer, and speaker.')
meta(name='keywords' content='garrett mills glmdev developer speaker flitter extollo student')
meta(name='author' content='Garrett Mills')
meta(name='robots' content='index, follow')
link(rel='author' href='/humans.txt')
link(rel="alternate" href="/feed/atom.xml" title="Garrett Mills - Notes (Atom)" type="application/atom+xml")
link(rel="alternate" href="/feed/rss.xml" title="Garrett Mills - Notes (RSS)" type="application/rss+xml")
link(rel="alternate" href="/feed/json.json" title="Garrett Mills - Notes (JSON)" type="application/feed+json")
link(rel="alternate" href="/blog/atom.xml" title="Garrett's Blog (Atom)" type="application/atom+xml")
link(rel="alternate" href="/blog/rss2.xml" title="Garrett's Blog (RSS)" type="application/rss+xml")
link(rel="alternate" href="/blog/json.json" title="Garrett's Blog (JSON)" type="application/feed+json")
include meta.html
block title
if title
title #{title} | Garrett Mills
else
title Garrett Mills
block style
// Register fonts here to avoid 2 layer network dependency tree for bundle.css
style.
@font-face {
font-family: 'Obsidian';
src: url('/assets/font/obsidian/Obsidian-Roman.otf') format('opentype');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "JetBrains Mono";
src: url("/assets/font/jetbrains-mono/JetBrainsMono-Regular.woff2") format('woff2');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Reckless";
src: url("/assets/font/reckless/WEB/Reckless-Regular.woff2") format('woff2');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Reckless";
src: url("/assets/font/reckless/WEB/Reckless-RegularItalic.woff2") format('woff2');
font-weight: normal;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: "Reckless";
src: url("/assets/font/reckless/WEB/Reckless-Bold.woff2") format('woff2');
font-weight: bold;
font-style: normal;
font-display: swap;
}
link(rel='stylesheet' href='/bundle.css')
body
.wrapper
header.hero glm.
nav
ul
li
a(href='/') Home
//li
a(href='/timeline') Timeline
li
a(href='/blog') Blog
li
a(href='/feed') Notes
li
a(href='/links') Bookmarks <img class="inline-markmark-logo" src="/assets/img/markmark-light.svg" eleventy:ignore alt="MarkMark logo"/>
block content
div.content-wrapper(role='main') !{content}
footer
.obsidian glm.
p &copy 2015-#{(new Date).getFullYear()} Garrett Mills — <a href="/technical">Technical Info</a><br><small><a href="/technical/#source-code-and-licensing">AI Scraping Notice</a></small>
block script

View File

@@ -0,0 +1,13 @@
{% layout 'obsidian.liquid' %}
{% block content %}
<div class="content-wrapper">
<p>You should be redirected shortly. If not, click <a href="{{ redirect_to }}">here</a>.</p>
</div>
{% block script %}
<script>
window.location.href = "{{ redirect_to }}"
</script>
{% endblock %}
{% endblock %}

View File

@@ -1,8 +0,0 @@
extends ./obsidian
block content
div.content-wrapper
p You should be redirected shortly. If not, click <a href="!{redirect_to}">here</a>.
script.
window.location.href = "!{redirect_to}"

19
src/blog/archive.liquid Normal file
View File

@@ -0,0 +1,19 @@
{% layout 'blog.liquid' %}
{% block blog_content %}
<h2>Post Archive</h2>
<div class="recent-posts">
{% for year in collections.blogByYear %}
<h3>{{ year.year }}</h3>
<ul class="plain">
{% for post in year.posts %}
<li>
<div class="secondary">{{ post.date | date: "%Y-%m-%d" }}</div>
<a class="title" href="{{ post.url }}">{{ post.data.title }}</a>
</li>
{% endfor %}
</ul>
{% endfor %}
</div>
{% endblock %}

View File

@@ -1,13 +0,0 @@
extends /blog
block blog_content
h2 Post Archive
.recent-posts
each year in collections.blogByYear
h3 #{year.year}
ul.plain
each post in year.posts
li
.secondary #{post.date.toISOString().split('T')[0]}
a.title(href=post.url) #{post.data.title}

24
src/blog/feeds.liquid Normal file
View File

@@ -0,0 +1,24 @@
---
layout: blog
---
{% renderFile 'src/blog/feeds-stub.md' %}
<h3>Garrett's RSS List</h3>
<blockquote>
This list is also available in the standard <a href="/assets/rss_opml.xml" download>OPML format</a>.
</blockquote>
{% for cat in collections.opmlByCategory %}
{% if cat.title == "Garrett Mills" %}
<h4 style="background-color: var(--c-font)">{{ cat.title }} (Shameless Self-Plug)</h4>
{% else %}
<h4 style="background-color: var(--c-font)">{{ cat.title }}</h4>
{% endif %}
<ul>
{% for sub in cat.subs %}
<li><a href="{{ sub.htmlUrl }}" download>{{ sub.title }}</a></li>
{% endfor %}
</ul>
{% endfor %}

View File

@@ -1,24 +0,0 @@
---
layout: blog
---
{% renderFile "src/blog/feeds-stub.md" %}
<h3>Garrett's RSS List</h3>
<blockquote>
This list is also available in the standard <a href="/assets/rss_opml.xml" download>OPML format</a>.
</blockquote>
{% for cat in collections.opmlByCategory %}
{% if (cat.title == "Garrett Mills") %}
<h4 style="background-color: var(--c-font)">{{ cat.title }} (Shameless Self-Plug)</h4>
{% else %}
<h4 style="background-color: var(--c-font)">{{ cat.title }}</h4>
{% endif %}
<ul>
{% for sub in cat.subs %}
<li><a href="{{ sub.htmlUrl }}" download>{{ sub.title }}</a></li>
{% endfor %}
</ul>
{% endfor %}

View File

@@ -30,7 +30,7 @@ metadata:
<category term="Technology"/>
<category term="Software Development"/>
{%- for post in collections.blog %}
{%- set absolutePostUrl = post.url | htmlBaseUrl(metadata.base) %}
{%- assign absolutePostUrl = post.url | htmlBaseUrl: metadata.base %}
<entry>
<title type="html"><![CDATA[{{ post.data.title }}]]></title>
<id>{{ absolutePostUrl }}</id>
@@ -41,7 +41,7 @@ metadata:
<email>{{ metadata.author.email }}</email>
<uri>{{ metadata.base }}/#about</uri>
</author>
<content type="html">{{ post.content | renderTransforms(post.data.page, metadata.base) }}</content>
<content type="html">{{ post.content | renderTransforms: post.data.page, metadata.base | xml_escape }}</content>
</entry>
{%- endfor %}
</feed>
</feed>

View File

@@ -0,0 +1,45 @@
---
permalink: /blog/json.json
eleventyExcludeFromCollections: true
metadata:
title: "Garrett's Blog"
description: "Write-ups and musings by Garrett Mills, often technical, sometimes not."
language: en
base: "https://garrettmills.dev"
author:
name: "Garrett Mills"
email: "shout@garrettmills.dev"
---
{
"version": "https://jsonfeed.org/version/1.1",
"title": "{{ metadata.title }}",
"language": "{{ metadata.language }}",
"home_page_url": "{{ metadata.base | addPathPrefixToFullUrl }}",
"feed_url": "{{ permalink | htmlBaseUrl: metadata.base }}",
"description": "{{ metadata.description }}",
"icon": "{{ metadata.base }}/assets/favicon/apple-touch-icon.png",
"authors": [
{
"name": "{{ metadata.author.name }}",
"url": "{{ metadata.base }}/#about"
}
],
"items": [
{%- for post in collections.blog %}
{%- capture absolutePostUrl %}{{ post.url | htmlBaseUrl: metadata.base }}{% endcapture %}
{
"id": "{{ absolutePostUrl }}",
"url": "{{ absolutePostUrl }}",
"title": "{{ post.data.title }}",
"content_html": {% if post.content %}{{ post.content | renderTransforms: post.data.page, metadata.base | json }}{% else %}""{% endif %},
"date_published": "{{ post.date | dateToRfc3339 }}",
"date_modified": "{{ post.date | dateToRfc3339 }}",
"author": {
"name": "{{ metadata.author.name }}",
"url": "{{ metadata.base }}/#about"
}
}
{% unless forloop.last %},{% endunless %}
{%- endfor %}
]
}

View File

@@ -1,45 +0,0 @@
---
permalink: /blog/json.json
eleventyExcludeFromCollections: true
metadata:
title: "Garrett's Blog"
description: "Write-ups and musings by Garrett Mills, often technical, sometimes not."
language: en
base: "https://garrettmills.dev"
author:
name: "Garrett Mills"
email: "shout@garrettmills.dev"
---
{
"version": "https://jsonfeed.org/version/1.1",
"title": "{{ metadata.title }}",
"language": "{{ metadata.language }}",
"home_page_url": "{{ metadata.base | addPathPrefixToFullUrl }}",
"feed_url": "{{ permalink | htmlBaseUrl(metadata.base) }}",
"description": "{{ metadata.description }}",
"icon": "{{ metadata.base }}/assets/favicon/apple-touch-icon.png",
"authors": [
{
"name": "{{ metadata.author.name }}",
"url": "{{ metadata.base }}/#about"
}
],
"items": [
{%- for post in collections.blog %}
{%- set absolutePostUrl %}{{ post.url | htmlBaseUrl(metadata.base) }}{% endset %}
{
"id": "{{ absolutePostUrl }}",
"url": "{{ absolutePostUrl }}",
"title": "{{ post.data.title }}",
"content_html": {% if post.content %}{{ post.content | renderTransforms(post.data.page, metadata.base) | dump | safe }}{% else %}""{% endif %},
"date_published": "{{ post.date | dateToRfc3339 }}",
"date_modified": "{{ post.date | dateToRfc3339 }}",
"author": {
"name": "{{ metadata.author.name }}",
"url": "{{ metadata.base }}/#about"
}
}
{% if not loop.last %},{% endif %}
{%- endfor %}
]
}

View File

@@ -28,10 +28,10 @@ metadata:
<copyright>Copyright (c) 2026 Garrett Mills. See website for licensing details.</copyright>
<category>Technology</category>
<category>Software Development</category>
<atom:link href="permalink | htmlBaseUrl(metadata.base)" rel="self" type="application/rss+xml"/>
<atom:link href="permalink | htmlBaseUrl: metadata.base" rel="self" type="application/rss+xml"/>
{%- for post in collections.blog %}
{%- set absolutePostUrl = post.url | htmlBaseUrl(metadata.base) %}
{%- assign absolutePostUrl = post.url | htmlBaseUrl: metadata.base %}
<item>
<title><![CDATA[{{ post.data.title }}]]></title>
<link>{{ absolutePostUrl }}</link>
@@ -39,9 +39,9 @@ metadata:
<pubDate>{{ post.date | dateToRfc822 }}</pubDate>
<author>{{ metadata.author.name }}</author>
<dc:creator>{{ metadata.author.name }}</dc:creator>
<description>{{ post.content | renderTransforms(post.data.page, metadata.base) }}</description>
<content:encoded>{{ post.content | renderTransforms(post.data.page, metadata.base) }}</content:encoded>
<description>{{ post.content | renderTransforms: post.data.page, metadata.base | xml_escape }}</description>
<content:encoded>{{ post.content | renderTransforms: post.data.page, metadata.base | xml_escape }}</content:encoded>
</item>
{%- endfor %}
</channel>
</rss>
</rss>

18
src/blog/index.liquid Normal file
View File

@@ -0,0 +1,18 @@
{% layout 'blog.liquid' %}
{% block blog_content %}
<p>Write-ups and musings, often technical, sometimes not.</p>
<h2>Recent(ish) Posts</h2>
<div class="recent-posts">
<ul class="plain">
{% for post in collections.blog reversed limit:10 %}
<li>
<div class="secondary">{{ post.data.date | date: "%Y-%m-%d" }}</div>
<a class="title" href="{{ post.url }}">{{ post.data.title }}</a>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}

View File

@@ -1,13 +0,0 @@
extends /blog
block blog_content
p Write-ups and musings, often technical, sometimes not.
h2 Recent(ish) Posts
.recent-posts
ul.plain
each post in collections.blog.reverse().slice(0, 10)
li
.secondary #{post.data.date.toISOString().split('T')[0]}
a.title(href=post.url) #{post.data.title}

21
src/blog/tag.liquid Normal file
View File

@@ -0,0 +1,21 @@
---
layout: blog
pagination:
data: collections.blogByTag
size: 1
alias: tag
permalink: "/blog/tag/{{ tag.tag }}/"
---
<h2>Posts w/ Tag: {{ tag.tag }}</h2>
<div class="recent-posts">
<ul class="plain">
{% for post in tag.posts %}
<li>
<div class="secondary">{{ post.date | date: "%Y-%m-%d" }}</div>
<a class="title" href="{{ post.url }}">{{ post.data.title }}</a>
</li>
{% endfor %}
</ul>
</div>

View File

@@ -1,21 +0,0 @@
---
layout: blog
pagination:
data: collections.blogByTag
size: 1
alias: tag
permalink: "/blog/tag/{{ tag.tag }}/"
---
<h2>Posts w/ Tag: {{ tag.tag }}</h2>
<div class="recent-posts">
<ul class="plain">
{% for post in tag.posts %}
<li>
<div class="secondary">{{ post.date.toISOString().split('T')[0] }}</div>
<a class="title" href="{{ post.url }}">{{ post.data.title }}</a>
</li>
{% endfor %}
</ul>
</div>

13
src/blog/tags.liquid Normal file
View File

@@ -0,0 +1,13 @@
{% layout 'blog.liquid' %}
{% block blog_content %}
<h2>Tags</h2>
<div class="post-tags listed">
<ul>
{% for tag in collections.blogByTag %}
<li><a class="button" href="/blog/tag/{{ tag.tag }}">#{{ tag.tag }}</a>&nbsp;&nbsp;&nbsp;<span style="color: var(--color-2); font-variant-ligatures: none;">({{ tag.posts | size }})</span></li>
{% endfor %}
</ul>
</div>
{% endblock %}

View File

@@ -1,9 +0,0 @@
extends /blog
block blog_content
h2 Tags
.post-tags.listed
ul
each tag in collections.blogByTag
li <a class="button" href="/blog/tag/#{tag.tag}">##{tag.tag}</a>&nbsp;&nbsp;&nbsp;<span style="color: var(--color-2); font-variant-ligatures: none;">(#{tag.posts.length})</a>

7
src/css-bundle.liquid Normal file
View File

@@ -0,0 +1,7 @@
---
permalink: bundle.css
---
{% include './assets/css/normalize.css' %}
{% include './assets/css/prism-cb.css' %}
{% include './assets/css/obsidian.css' %}
{% include './assets/css/feed.css' %}

View File

@@ -1,7 +0,0 @@
---
permalink: bundle.css
---
{% include "./assets/css/normalize.css" %}
{% include "./assets/css/prism-cb.css" %}
{% include "./assets/css/obsidian.css" %}
{% include "./assets/css/feed.css" %}

View File

@@ -30,7 +30,7 @@ metadata:
<category term="Technology"/>
<category term="Software Development"/>
{%- for post in collections.feedDesc %}
{%- set absolutePostUrl = post.url | htmlBaseUrl(metadata.base) %}
{%- assign absolutePostUrl = post.url | htmlBaseUrl: metadata.base %}
<entry>
<title type="html"><![CDATA[{{ post.data.title }}]]></title>
<id>{{ absolutePostUrl }}</id>
@@ -41,7 +41,7 @@ metadata:
<email>{{ metadata.author.email }}</email>
<uri>{{ metadata.base }}/#about</uri>
</author>
<content type="html">{{ post.content | renderTransforms(post.data.page, metadata.base) }}</content>
<content type="html">{{ post.content | renderTransforms: post.data.page, metadata.base | xml_escape }}</content>
</entry>
{%- endfor %}
</feed>
</feed>

View File

@@ -0,0 +1,45 @@
---
permalink: /feed/json.json
eleventyExcludeFromCollections: true
metadata:
title: "Garrett Mills - Notes"
description: "Misc notes, posts, links, and updates from garrettmills.dev."
language: en
base: "https://garrettmills.dev"
author:
name: "Garrett Mills"
email: "shout@garrettmills.dev"
---
{
"version": "https://jsonfeed.org/version/1.1",
"title": "{{ metadata.title }}",
"language": "{{ metadata.language }}",
"home_page_url": "{{ metadata.base | addPathPrefixToFullUrl }}",
"feed_url": "{{ permalink | htmlBaseUrl: metadata.base }}",
"description": "{{ metadata.description }}",
"icon": "{{ metadata.base }}/assets/favicon/apple-touch-icon.png",
"authors": [
{
"name": "{{ metadata.author.name }}",
"url": "{{ metadata.base }}/#about"
}
],
"items": [
{%- for post in collections.feedDesc %}
{%- capture absolutePostUrl %}{{ post.url | htmlBaseUrl: metadata.base }}{% endcapture %}
{
"id": "{{ absolutePostUrl }}",
"url": "{{ absolutePostUrl }}",
"title": "{{ post.data.title }}",
"content_html": {% if post.content %}{{ post.content | renderTransforms: post.data.page, metadata.base | json }}{% else %}""{% endif %},
"date_published": "{{ post.date | dateToRfc3339 }}",
"date_modified": "{{ post.date | dateToRfc3339 }}",
"author": {
"name": "{{ metadata.author.name }}",
"url": "{{ metadata.base }}/#about"
}
}
{% unless forloop.last %},{% endunless %}
{%- endfor %}
]
}

View File

@@ -1,45 +0,0 @@
---
permalink: /feed/json.json
eleventyExcludeFromCollections: true
metadata:
title: "Garrett Mills - Notes"
description: "Misc notes, posts, links, and updates from garrettmills.dev."
language: en
base: "https://garrettmills.dev"
author:
name: "Garrett Mills"
email: "shout@garrettmills.dev"
---
{
"version": "https://jsonfeed.org/version/1.1",
"title": "{{ metadata.title }}",
"language": "{{ metadata.language }}",
"home_page_url": "{{ metadata.base | addPathPrefixToFullUrl }}",
"feed_url": "{{ permalink | htmlBaseUrl(metadata.base) }}",
"description": "{{ metadata.description }}",
"icon": "{{ metadata.base }}/assets/favicon/apple-touch-icon.png",
"authors": [
{
"name": "{{ metadata.author.name }}",
"url": "{{ metadata.base }}/#about"
}
],
"items": [
{%- for post in collections.feedDesc %}
{%- set absolutePostUrl %}{{ post.url | htmlBaseUrl(metadata.base) }}{% endset %}
{
"id": "{{ absolutePostUrl }}",
"url": "{{ absolutePostUrl }}",
"title": "{{ post.data.title }}",
"content_html": {% if post.content %}{{ post.content | renderTransforms(post.data.page, metadata.base) | dump | safe }}{% else %}""{% endif %},
"date_published": "{{ post.date | dateToRfc3339 }}",
"date_modified": "{{ post.date | dateToRfc3339 }}",
"author": {
"name": "{{ metadata.author.name }}",
"url": "{{ metadata.base }}/#about"
}
}
{% if not loop.last %},{% endif %}
{%- endfor %}
]
}

View File

@@ -28,10 +28,10 @@ metadata:
<copyright>Copyright (c) 2026 Garrett Mills. See website for licensing details.</copyright>
<category>Technology</category>
<category>Software Development</category>
<atom:link href="permalink | htmlBaseUrl(metadata.base)" rel="self" type="application/rss+xml"/>
<atom:link href="permalink | htmlBaseUrl: metadata.base" rel="self" type="application/rss+xml"/>
{%- for post in collections.feedDesc %}
{%- set absolutePostUrl = post.url | htmlBaseUrl(metadata.base) %}
{%- assign absolutePostUrl = post.url | htmlBaseUrl: metadata.base %}
<item>
<title><![CDATA[{{ post.data.title }}]]></title>
<link>{{ absolutePostUrl }}</link>
@@ -39,9 +39,9 @@ metadata:
<pubDate>{{ post.date | dateToRfc822 }}</pubDate>
<author>{{ metadata.author.name }}</author>
<dc:creator>{{ metadata.author.name }}</dc:creator>
<description>{{ post.content | renderTransforms(post.data.page, metadata.base) }}</description>
<content:encoded>{{ post.content | renderTransforms(post.data.page, metadata.base) }}</content:encoded>
<description>{{ post.content | renderTransforms: post.data.page, metadata.base | xml_escape }}</description>
<content:encoded>{{ post.content | renderTransforms: post.data.page, metadata.base | xml_escape }}</content:encoded>
</item>
{%- endfor %}
</channel>
</rss>
</rss>

33
src/feed/index.liquid Normal file
View File

@@ -0,0 +1,33 @@
{% layout 'obsidian.liquid' %}
{% block content %}
<div class="container feed" id="top">
<h1>Notes</h1>
<p class="button-links">
<a class="button" href="/feed/rss.xml">RSS</a>
<a class="button" href="/feed/atom.xml">Atom</a>
<a class="button" href="/feed/json.json">JSON</a>
</p>
<section id="posts">
{% for post in collections.feedDesc %}
<div class="post" id="{{ post.data.slug }}">
{% if post.data.feedtags %}
<div class="tags">
{% for tag in post.data.feedtags %}
<a class="tag" href="#">{{ tag }}</a>
{% endfor %}
</div>
{% endif %}
<h2>{{ post.data.title }}</h2>
<div class="content-wrapper">{{ post.content }}</div>
<div class="footer">
<a class="permalink" href="{{ post.url }}">permalink (v2)</a>
<span class="sep">|</span>
<span class="date">{{ post.date | date: "%m/%d/%Y" }}</span>
</div>
</div>
{% endfor %}
</section>
</div>
{% endblock %}

View File

@@ -1,23 +0,0 @@
extends /obsidian
block content
.container.feed#top
h1 Notes
p.button-links
a.button(href='/feed/rss.xml') RSS
a.button(href='/feed/atom.xml') Atom
a.button(href='/feed/json.json') JSON
section#posts
each post in collections.feedDesc
.post(id=post.data.slug)
if post.data.feedtags
.tags
each tag in post.data.feedtags
a.tag(href="#") #{tag}
h2 #{post.data.title}
.content-wrapper !{post.content}
.footer
a.permalink(href=post.url) permalink (v2)
span.sep |
span.date #{post.date.toLocaleDateString()}