feat: derive gardenStage from nested tags (garden/cultivate)
- eleventyComputed in content.11tydata.js resolves gardenStage from category/tags at build time — no explicit gardenStage frontmatter needed - withoutGardenTags filter strips garden/* from category pill rendering - categories collection excludes garden/* entries (no phantom category pages) - All list templates and post layout use withoutGardenTags filter
This commit is contained in:
@@ -61,12 +61,12 @@
|
||||
<time-difference><time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time></time-difference>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -101,12 +101,12 @@
|
||||
<time-difference><time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time></time-difference>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -146,12 +146,12 @@
|
||||
<time-difference><time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time></time-difference>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -186,12 +186,12 @@
|
||||
<time-difference><time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time></time-difference>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -227,12 +227,12 @@
|
||||
<time-difference><time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time></time-difference>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -272,12 +272,12 @@
|
||||
<time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -303,12 +303,12 @@
|
||||
{{ post.date | dateDisplay }}
|
||||
</time></time-difference>
|
||||
</a>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories ml-2">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
@@ -31,13 +31,13 @@ withBlogSidebar: true
|
||||
<time-difference><time class="dt-published font-mono text-sm" datetime="{{ date.toISOString() }}">
|
||||
{{ date | dateDisplay }}
|
||||
</time></time-difference>
|
||||
{% if category %}
|
||||
{% if category | withoutGardenTags %}
|
||||
<ul class="post-categories flex flex-wrap gap-2 list-none p-0 m-0" role="list" aria-label="Categories">
|
||||
{# Handle both string and array categories #}
|
||||
{% if category is string %}
|
||||
<li><a href="/categories/{{ category | slugify }}/" class="p-category">{{ category }}</a></li>
|
||||
{% else %}
|
||||
{% for cat in category %}
|
||||
{% for cat in (category | withoutGardenTags) %}
|
||||
<li><a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a></li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -233,11 +233,11 @@ withBlogSidebar: true
|
||||
{% if gardenStage %}
|
||||
<span data-pagefind-filter="garden-stage">{{ gardenStage }}</span>
|
||||
{% endif %}
|
||||
{% if category %}
|
||||
{% if category | withoutGardenTags %}
|
||||
{% if category is string %}
|
||||
<span data-pagefind-filter="category">{{ category }}</span>
|
||||
{% else %}
|
||||
{% for cat in category %}
|
||||
{% for cat in (category | withoutGardenTags) %}
|
||||
<span data-pagefind-filter="category">{{ cat }}</span>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
@@ -37,12 +37,12 @@ permalink: "articles/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNu
|
||||
<time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
28
blog.njk
28
blog.njk
@@ -69,12 +69,12 @@ permalink: "blog/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNumber
|
||||
<time-difference><time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time></time-difference>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -109,12 +109,12 @@ permalink: "blog/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNumber
|
||||
<time-difference><time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time></time-difference>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -154,12 +154,12 @@ permalink: "blog/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNumber
|
||||
<time-difference><time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time></time-difference>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -194,12 +194,12 @@ permalink: "blog/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNumber
|
||||
<time-difference><time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time></time-difference>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -233,12 +233,12 @@ permalink: "blog/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNumber
|
||||
<time-difference><time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time></time-difference>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -278,12 +278,12 @@ permalink: "blog/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNumber
|
||||
<time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -307,12 +307,12 @@ permalink: "blog/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNumber
|
||||
{{ post.date | dateDisplay }}
|
||||
</time></time-difference>
|
||||
</a>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories ml-2">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
@@ -39,12 +39,12 @@ permalink: "bookmarks/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageN
|
||||
<time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
@@ -14,9 +14,39 @@ const normalizePermalink = (permalink) => {
|
||||
return permalink;
|
||||
};
|
||||
|
||||
/** Valid garden stages — keep in sync with eleventy.config.js gardenStageInfo */
|
||||
const GARDEN_STAGES = new Set([
|
||||
"plant", "cultivate", "evergreen", "question", "repot", "revitalize", "revisit",
|
||||
]);
|
||||
|
||||
const GARDEN_PREFIX = "garden/";
|
||||
|
||||
/**
|
||||
* Derive gardenStage from nested tags/categories (e.g. "garden/cultivate")
|
||||
* if the post doesn't already have an explicit gardenStage frontmatter property.
|
||||
* Handles both string and array values for `category` and `tags`.
|
||||
* Works with or without a leading `#`.
|
||||
*/
|
||||
const deriveGardenStage = (data) => {
|
||||
if (data.gardenStage) return data.gardenStage;
|
||||
const fields = [data.category, data.tags].flat().filter(Boolean);
|
||||
for (const tag of fields) {
|
||||
const clean = String(tag).replace(/^#/, "");
|
||||
if (clean.startsWith(GARDEN_PREFIX)) {
|
||||
const stage = clean.slice(GARDEN_PREFIX.length);
|
||||
if (GARDEN_STAGES.has(stage)) return stage;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export default {
|
||||
layout: "layouts/post.njk",
|
||||
eleventyComputed: {
|
||||
permalink: (data) => normalizePermalink(data.permalink),
|
||||
// Derive gardenStage from nested tags if not set explicitly in frontmatter.
|
||||
// A post with category: [garden/cultivate, dev] gets gardenStage: "cultivate"
|
||||
// automatically, with no other changes needed downstream.
|
||||
gardenStage: (data) => deriveGardenStage(data),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -950,6 +950,18 @@ export default function (eleventyConfig) {
|
||||
return stages[stage] || null;
|
||||
});
|
||||
|
||||
// Strip garden/* tags from a category list so they don't render as
|
||||
// plain category pills alongside the garden badge.
|
||||
eleventyConfig.addFilter("withoutGardenTags", (categories) => {
|
||||
if (!categories) return categories;
|
||||
const arr = Array.isArray(categories) ? categories : [categories];
|
||||
const filtered = arr.filter(
|
||||
(c) => !String(c).replace(/^#/, "").startsWith("garden/"),
|
||||
);
|
||||
if (!Array.isArray(categories)) return filtered[0] ?? null;
|
||||
return filtered;
|
||||
});
|
||||
|
||||
// Collections for different post types
|
||||
// Note: content path is content/ due to symlink structure
|
||||
// "posts" shows ALL content types combined
|
||||
@@ -1057,6 +1069,8 @@ export default function (eleventyConfig) {
|
||||
const cats = Array.isArray(item.data.category) ? item.data.category : [item.data.category];
|
||||
cats.forEach((cat) => {
|
||||
if (cat && typeof cat === 'string' && cat.trim()) {
|
||||
// Exclude garden/* tags — they're rendered as garden badges, not categories
|
||||
if (cat.replace(/^#/, "").startsWith("garden/")) return;
|
||||
const slug = slugify(cat.trim());
|
||||
if (slug && !categoryMap.has(slug)) {
|
||||
categoryMap.set(slug, cat.trim());
|
||||
|
||||
@@ -37,12 +37,12 @@ permalink: "likes/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNumbe
|
||||
<time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
@@ -32,12 +32,12 @@ permalink: "notes/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNumbe
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
</a>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories ml-2">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
@@ -30,12 +30,12 @@ permalink: "photos/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNumb
|
||||
<time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
@@ -42,12 +42,12 @@ permalink: "replies/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNum
|
||||
<time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
@@ -42,12 +42,12 @@ permalink: "reposts/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNum
|
||||
<time class="dt-published font-mono text-sm" datetime="{{ post.date | isoDate }}">
|
||||
{{ post.date | dateDisplay }}
|
||||
</time>
|
||||
{% if post.data.category %}
|
||||
{% if post.data.category | withoutGardenTags %}
|
||||
<span class="post-categories">
|
||||
{% if post.data.category is string %}
|
||||
<a href="/categories/{{ post.data.category | slugify }}/" class="p-category">{{ post.data.category }}</a>
|
||||
{% else %}
|
||||
{% for cat in post.data.category %}
|
||||
{% for cat in (post.data.category | withoutGardenTags) %}
|
||||
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
Reference in New Issue
Block a user