Skip to content

Commit

Permalink
Fix duplicate tags bug on /tags/
Browse files Browse the repository at this point in the history
  • Loading branch information
AleksandrHovhannisyan committed Nov 29, 2022
1 parent 7ed63df commit f239391
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 23 deletions.
2 changes: 0 additions & 2 deletions .eleventy.js
Expand Up @@ -34,7 +34,6 @@ const {
getAllPosts,
getAllUniqueCategories,
getPostsByCategory,
getPopularCategories,
} = require('./config/collections');
const markdownLib = require('./config/plugins/markdown');
const { dir, imagePaths, scriptDirs } = require('./config/constants');
Expand Down Expand Up @@ -99,7 +98,6 @@ module.exports = (eleventyConfig) => {
eleventyConfig.addCollection('posts', getAllPosts);
eleventyConfig.addCollection('categories', getAllUniqueCategories);
eleventyConfig.addCollection('postsByCategory', getPostsByCategory);
eleventyConfig.addCollection('popularCategories', getPopularCategories({ limit: 10, minCount: 5 }));

// Plugins
eleventyConfig.addPlugin(PluginFootnotes, {
Expand Down
52 changes: 34 additions & 18 deletions config/collections/index.js
@@ -1,7 +1,6 @@
const lodash = require('lodash');
const { getAllUniqueKeyValues, slugifyString } = require('../utils');
const site = require('../../src/_data/site');
const { limit } = require('../filters/filters');
const { dir } = require('../constants');

/** Returns all blog posts as a collection. */
Expand All @@ -10,17 +9,45 @@ const getAllPosts = (collection) => {
return posts.reverse();
};

/** Given a category name and an optional page number, returns the root-relative URL to that category's page.
* @param {string} category
* @param {number} [page] The one-indexed page number
*/
const getCategoryHref = (category, page) => {
const slug = slugifyString(category);
return page > 1 ? `/tags/${slug}/page/${page}/` : `/tags/${slug}/`;
};

/** Returns all unique categories as a collection.
* NOTE: I'm calling these "categories" to distinguish them from 11ty's built-in "tags." However,
* these are still referred to as tags in the UI since that's what's most common.
* @returns {({ title: string; href: string; count: string })[]}
*/
const getAllUniqueCategories = (collection) => {
const allPosts = getAllPosts(collection);
const categories = getAllUniqueKeyValues(allPosts, 'categories').map((category) => ({
title: category,
slug: slugifyString(category),
}));
return categories;
const uniqueCategories = getAllUniqueKeyValues(allPosts, 'categories');

// Do this separately for performance rather than inside the category map logic below, which would be several levels of nesting loops
const categoryCounts = allPosts.reduce((categoryCounts, post) => {
post.data.categories?.forEach((category) => {
if (!categoryCounts[category]) {
categoryCounts[category] = 0;
}
categoryCounts[category]++;
});
return categoryCounts;
}, {});

return (
uniqueCategories
.map((category) => ({
title: category,
href: getCategoryHref(category),
count: categoryCounts[category],
}))
// Popular categories first
.sort((a, b) => b.count - a.count)
);
};

// Blog posts by category, for pagination
Expand All @@ -41,10 +68,7 @@ const getPostsByCategory = (collection) => {
const chunkedCategoryPosts = lodash.chunk(categoryPosts, postsPerPage);

// Map each chunk to its page slug
const categorySlug = slugifyString(category);
const pageHrefs = chunkedCategoryPosts.map((_, i) =>
i > 0 ? `/tags/${categorySlug}/page/${i + 1}/` : `/tags/${categorySlug}/`
);
const pageHrefs = chunkedCategoryPosts.map((_, pageIndex) => getCategoryHref(category, pageIndex + 1));

chunkedCategoryPosts.forEach((posts, index) => {
// Massage the data into a format that 11ty's pagination will like
Expand All @@ -69,16 +93,8 @@ const getPostsByCategory = (collection) => {
return blogPostsByCategory.sort((category1, category2) => category2.posts.length - category1.posts.length);
};

/** Returns the top `n` categories with at least `minCount` posts, in descending order. */
const getPopularCategories = (params) => (collection) => {
const categories = getPostsByCategory(collection).filter((category) => category.posts.length >= params.minCount);
const popularCategories = limit(categories, params.limit);
return popularCategories;
};

module.exports = {
getAllPosts,
getAllUniqueCategories,
getPostsByCategory,
getPopularCategories,
};
6 changes: 3 additions & 3 deletions src/_pages/tags.html
Expand Up @@ -22,11 +22,11 @@
<h1 class="hero-title">All Tags</h1>
<nav aria-label="Tags">
<ol class="pill-group">
{%- for tag in collections.postsByCategory %}
{%- for tag in collections.categories %}
<li>
<a href="{{ tag.href }}" class="pill" data-shape="round" data-size="sm">
{{ tag.title }}&nbsp;<span class="pill-count" aria-hidden="true">{{ tag.posts | size }}</span
><span class="screen-reader-only">{{ tag.posts | size }} posts</span>
{{ tag.title }}&nbsp;<span class="pill-count" aria-hidden="true">{{ tag.count }}</span
><span class="screen-reader-only">{{ tag.count }} posts</span>
</a>
</li>
{% endfor %}
Expand Down

0 comments on commit f239391

Please sign in to comment.