Last active
July 25, 2024 16:40
-
-
Save robweychert/98cd6ddd8675c9ff645c311bd636c604 to your computer and use it in GitHub Desktop.
Custom collections in Eleventy based on your posts’ front matter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = function(eleventyConfig) { | |
// Make a custom collection based on a key in your posts' front matter | |
function addCollectionByKey(collectionName, postKey, paginate=true, postsPerPage=100) { | |
eleventyConfig.addCollection(collectionName, function(collectionApi) { | |
const collectionObjects = {}; | |
let collectionFinal = []; | |
// Filter the posts that have the chosen key in their metadata | |
let collectionPosts = collectionApi.getAll().filter(function(post) { | |
return postKey in post.data; | |
}); | |
// Sort the posts in descending order by date | |
// (Comment this part out if date is unavailable or irrelevant) | |
collectionPosts = collectionPosts.sort(function(a, b) { | |
return b.date - a.date; | |
}); | |
// Loop through the posts | |
collectionPosts.forEach(function(post) { | |
let postValue = post.data[postKey]; // The chosen key's value in the current post | |
// If the chosen key is `date`, the value needs some manipulation | |
if (postKey === "date") { | |
const postDate = new Date(post.data.date); | |
// postValue = "YYYY/MM"; | |
postValue = postDate.getFullYear().toString() + "/" + (postDate.getMonth() + 1).toString().padStart(2, "0"); | |
} | |
// This function finds every unique value (tag) associated with the chosen key | |
function collectionizeTag(tag) { | |
// If the tag isn't represented in collectionObjects, | |
// make it a key in collectionObjects with an empty array value | |
if (!collectionObjects.hasOwnProperty(tag)) { | |
collectionObjects[tag] = []; | |
} | |
// Add the current post to the array associated with this tag | |
collectionObjects[tag].push(post); | |
} | |
// If the chosen key has multiple tags | |
if (typeof postValue === "object") { | |
// Loop through the tags and run collectionizeTag on each tag | |
for (let i = 0; i < postValue.length; i++) { | |
collectionizeTag(post.data[postKey][i]); | |
} | |
// Otherwise run collectionizeTag on the key's single tag | |
} else { | |
collectionizeTag(postValue); | |
} | |
}); | |
/* | |
collectionObjects now looks something like this: | |
{ | |
"tag1": [ {post2}, {post1} ], | |
"tag2": [ {post2}, {post1} ] | |
} | |
*/ | |
// If you want each tag archive to be paginated, the contents of | |
// collectionObjects need to be reformatted | |
if (paginate) { | |
// Loop through the tags | |
for (const tag in collectionObjects) { | |
let page = 0; | |
// Loop through the posts associated with the tag | |
for (let i = 0; i < collectionObjects[tag].length; i++) { | |
// Determine how many total pages there will be based on | |
// the number of posts and postsPerPage | |
let pageTotal = Math.ceil(collectionObjects[tag].length / postsPerPage); | |
// If this is the first post, or the current page is at capacity, add a new page | |
if (page === 0 || collectionFinal[collectionFinal.length - 1]["pageData"].length === postsPerPage) { | |
page++; | |
collectionFinal.push({"name": tag, "pageNumber": page, "pageTotal": pageTotal, "pageData": []}); | |
} | |
// Add this post to the latest page | |
collectionFinal[collectionFinal.length - 1]["pageData"].push(collectionObjects[tag][i]); | |
} | |
// Reset the page count for each tag | |
page = 0; | |
} | |
/* | |
collectionFinal now looks something like this: | |
[ | |
{ "name": "tag1", "pageNumber": 1, "pageTotal": 2, "pageData": [ {post4}, {post3} ] }, | |
{ "name": "tag1", "pageNumber": 2, "pageTotal": 2, "pageData": [ {post2}, {post1} ] }, | |
{ "name": "tag2", "pageNumber": 1, "pageTotal": 2, "pageData": [ {post4}, {post3} ] }, | |
{ "name": "tag2", "pageNumber": 2, "pageTotal": 2, "pageData": [ {post2}, {post1} ] } | |
] | |
*/ | |
// If each tag archive doesn't need to be paginated, | |
// no reformatting is necessary | |
} else { | |
collectionFinal = collectionObjects; | |
} | |
return collectionFinal; | |
}); | |
}; | |
addCollectionByKey("postsByMonth", "date"); | |
addCollectionByKey("postsByTopic", "topic", false); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
pagination: | |
data: collections.postsByMonth | |
size: 1 | |
alias: month | |
permalink: "/blog/{{ month.name }}/{% if month.pageNumber %}{{ month.pageNumber }}/{% endif %}" | |
layout: layouts/base.njk | |
--- | |
<h1>Month: “{{ month.name }}” {% if month.pageNumber %}({{ month.pageNumber }} of {{ month.pageTotal }}){% endif %}</h1> | |
{% set monthArchives = month.pageData %} | |
<ul> | |
{% for post in monthArchives %} | |
<li>{{ post.fileSlug }}</li> | |
{% endfor %} | |
</ul> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
pagination: | |
data: collections.postsByTopic | |
size: 1 | |
alias: topic | |
permalink: "/blog/topic/{{ topic | slugify }}/ %}" | |
layout: layouts/base.njk | |
--- | |
<h1>Topic: “{{ topic }}”</h1> | |
{% set topicArchives = collections[postsByTopic][topic] %} | |
<ul> | |
{% for post in topicArchives %} | |
<li>{{ post.data.title }}</li> | |
{% endfor %} | |
</ul> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment