chore: post
This commit is contained in:
parent
a9e55c22d2
commit
cfa73985cf
1 changed files with 74 additions and 0 deletions
74
src/posts/2024/surfacing-most-used-tags-in-eleventy.md
Normal file
74
src/posts/2024/surfacing-most-used-tags-in-eleventy.md
Normal file
|
@ -0,0 +1,74 @@
|
|||
---
|
||||
date: '2024-03-09'
|
||||
title: 'Surfacing most used tags in Eleventy'
|
||||
description: "I made some lightweight design changes to my site, keeping things simple but moving the date up above post headers, surfacing tags below and restoring `Read more` links."
|
||||
tags: ['Eleventy', 'development', 'javascript']
|
||||
---
|
||||
I made some lightweight design changes to my site, keeping things simple but moving the date up above post headers, surfacing tags below and restoring `Read more` links.<!-- excerpt -->
|
||||
|
||||
As part of this I dropped my dedicated Tags page and built a collection to surface my most used tags, sorted in descending order that I could display in a reusable Liquid partial. I use this partial to populate post tags and new tag displays on my search page, 404 and contact success views. The code for the collection looks like this:
|
||||
|
||||
```javascript
|
||||
export const tagsSortedByCount = (collectionApi) => {
|
||||
const tagStats = {};
|
||||
const posts = collectionApi.getFilteredByGlob('src/posts/**/*.*');
|
||||
posts.forEach((post) => {
|
||||
post.data.tags.forEach((tag) => {
|
||||
if (!tagStats[tag]) tagStats[tag] = 1;
|
||||
if (tagStats[tag]) tagStats[tag] = tagStats[tag] + 1;
|
||||
});
|
||||
});
|
||||
const deletedTags = ['posts'];
|
||||
deletedTags.forEach(tag => delete tagStats[tag]);
|
||||
const tagStatsArr = Object.entries(tagStats);
|
||||
return tagStatsArr.sort((a, b) => b[1] - a[1]).map(([key, value]) => `${key}`);
|
||||
}
|
||||
```
|
||||
|
||||
I pass in the collection API, filter for posts using the `getFiltedByGlob` method and then iterate through each post object, then through the tags contained therein[^1]. This is done to build an object containing each tag as a key and the frequency of use as a value.
|
||||
|
||||
Finally, I iterate through my `deletedTags` array (which could contain anything you'd like), generate an array from the `tagStats` object, sort it by cound and return an array of strings in the proper order.
|
||||
|
||||
This `tagsSortedByCount` collection is imported into my `.eleventy.js` along with my other custom collections:
|
||||
|
||||
```javascript
|
||||
import { tagList, tagMap, postStats, tagsSortedByCount } from './config/collections/index.js'
|
||||
...
|
||||
eleventyConfig.addCollection('tagsSortedByCount', tagsSortedByCount)
|
||||
````
|
||||
|
||||
And can then be leveraged in my Liquid partial as follows:
|
||||
|
||||
{% raw %}
|
||||
```liquid
|
||||
{% render "partials/tags.liquid", tags:collections.tagsSortedByCount %}
|
||||
```
|
||||
{% endraw %}
|
||||
|
||||
The partial displays up to `10` tags:
|
||||
|
||||
{% raw %}
|
||||
```liquid
|
||||
{% assign filteredTags = tags | filterTags %}
|
||||
{% for tag in filteredTags limit: 10 %}
|
||||
<a class="tag" href="/tags/{{ tag | downcase }}" data-pagefind-filter="tags">{{ tag | formatTag }}</a>
|
||||
{% endfor %}
|
||||
```
|
||||
{% endraw %}
|
||||
|
||||
While also making use of a filter to format the tags for display called `formatTag`:
|
||||
|
||||
```javascript
|
||||
formatTag: (string) => {
|
||||
const capitalizeFirstLetter = (string) => {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
}
|
||||
if (string === 'iOS' || string === 'macOS') return `#${string}`
|
||||
if (!string.includes(' ')) return `#${capitalizeFirstLetter(string)}`
|
||||
return `#${string.split(' ').map(s => capitalizeFirstLetter(s)).join('')}`
|
||||
}
|
||||
```
|
||||
|
||||
Now, with all that in place, I can consistently display post and most used tags across my site.
|
||||
|
||||
[^1]: Nested loops, gross, I know.
|
Reference in a new issue