Skip to content

Instantly share code, notes, and snippets.

@tannerdolby
Last active February 10, 2023 19:52
Show Gist options
  • Save tannerdolby/0fd575a480d0299e1d6735f462799d77 to your computer and use it in GitHub Desktop.
Save tannerdolby/0fd575a480d0299e1d6735f462799d77 to your computer and use it in GitHub Desktop.
11ty filter for returning a sorted list of tags from collections. Use the it in a template like {{ collections.foo | taglist }} to get the sorted tag list.
eleventyConfig.addFilter("taglist", function(collection) {
const tags = [];
collection.forEach(post => {
tags.push(...post.data.tags);
});
const sorted = [...new Set(tags)].sort((a, b) => a.localeCompare(b));
return sorted;
});
@tannerdolby
Copy link
Author

tannerdolby commented Aug 14, 2021

More discussion based on this tweet:

Great tip but javascript syntax is so a mess to read for me. { ( => ... arrow function spread operator etc.
Would you add some comments to explain or use no shortcuts to help noobs ?

Here is an implementation with comments and less ES6 usage:

eleventyConfig.addFilter("taglist", function(collection) {
        // Creates an empty array to store tags in later on
        let tags = [];

        // iterate over the array of objects represented by the 
        // `collection` variable passed to the callback function
        for (var i = 0; i < collection.length; i++) {
            // collection[i].data.tags is an array in the form of
            // ["tag1", "tag2"] which is an iterable data structure.
            // We can use the spread operator (ES6 feature) `...` to "expand" 
            // the values present in each iterable array of tags then add them into
            // the `tags` array for later processing
            // tags.push(...collection[i].data.tags);

            // if we didn't want to use any ES6 and forego using spread syntax,
            // just loop through each iterable array of tags and push the tag values
            // into the `tags` array
            tags.push(collection[i].data.tags);
        }
        console.log(tags); // [['typescript', 'javascript'], ['scss', 'css']]

        // We pushed each tags array (which is iterable)
        // into the `tags` variable, so its now an array of arrays
        // since we want to "expand" each 1D tags array, we can simply
        // flatten the `tags` array so its only an array of tag strings
        flat = tags.flat(); 
        console.log(flat) // ['typescript', 'javascript', 'scss', 'css'] etc

        // The Set object allows us to store unique values of any type,
        // so we will convert our `tags` array to a Set and then
        // sort the unique list of tags in alphabetical order
        let set = new Set(flat.sort(function(a, b) {
            return a.localeCompare(b)
        }));

        // Returning a Set object with the alphabetically sorted taglist,
        // You could expand the set into an array if you want to return an array like I've
        // done in the first gist above, but either way works :)
        return set;
    });

as the comments introduce quite a bit of "bloat", the above code without comments looks like:

eleventyConfig.addFilter("taglist", function(collection) {
        let tags = [];
        for (var i = 0; i < collection.length; i++) {
            tags.push(collection[i].data.tags);
        }
        flat = tags.flat(); 
        let set = new Set(flat.sort(function(a, b) {
            return a.localeCompare(b)
        }));

        return set;
    });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment