Open oupala opened 7 years ago
I'm new to using this plugin, so please excuse my misconceptions, if any.
I'm not sure this plugin's use case fits listing all tags on a page. I thought it was meant to allow you to paginate / group posts by tags. For all your listed concerns, there are no direct options in this plugin that you can set to solve your problem. I've thought of some alternative solutions, if you're interested:
Although there is a sortBy
option available, this is for ordering the files with tags within an array for pagination, not the tags themselves. If you have a page already that lists all tags, you could, in your templating engine perform a sort to achieve an alphabetized list. Or if you have the list, javascript has a builtin .sort()
for arrays.
Counting: this plugin can add a tags
property to your metalsmith global metadata object (use the metadataKey
option). The format for that object like this: { tag1: [Array], tag2: [Array], tag3: [Array] ...} }
where each tag keys to an array of other file objects. You can calculate length from there to get a count.
You third concern, I would probably look at the tag index files, where you can access the pagination
field. You can look at the array of files each index has under it, so you could come up with something to see if the counts for all index pages of that particular tag exceed your x=3.
I don't know if that was any help at all. You asked in September, and it's months later. What solution did you come up with?
I have a special handlebars template for displaying all tags:
<div class="container">
<ul class="tags-list">
{{#each tags}}
<li><a href="/tags/{{urlSafe}}/">{{@key}}</a></li>
{{/each}}
</ul>
</div>
I might have to look at handlebars on how to order tags instead of simply listing them by {{#each tags}}
.
And I have absolutely no idea on how to add a counter on tags to know how many time they are used.
As you can see, I also respond you months after your answer, and I still not have found any solution.
I've never written handlebars but I can link to some docs.
You can do what you want in Handlebars. This relevant doc tells you how to access properties of your array using the #with
block, but I think a this.length
in the loop will also give you the length of the array (aka, number of posts with a particular tag).
You will also need to create a helper for a way to use an #if
block to only display tags if there is a post threshold met. A tutorial, or follow the doc
And you might need a lookup
call to get the key (tag name), of your tags
object inside the #with
block, but you might be able to do it without. I suspect your template structure to look something like (untested):
<div class="container">
<ul class="tags-list">
{{#each tags}}
{{#with this}}
<!-- some if statement here to guard the <li> by checking for length -->
<li><a href="/tags/{{urlSafe}}/">
<!-- lookup call to get the key, which is the name of the tag -->
({{ length }})</a></li>
{{/with}}
{{/each}}
</ul>
</div>
I found a partial solution with a helper.
Here is the solution for ordering tags:
{{#each_with_sort tags}}
<li><a href="/tags/{{urlSafe}}/" class="badge badge-secondary" aria-label="tag {{name}}">{{name}}</a></li>
{{/each_with_sort}}
Handlebars.registerHelper('each_with_sort', function(object, options) {
console.log(object);
var keys = Object.keys(object);
var array = [];
keys.forEach(key => {
array.push({
name: key,
data: object[key][0], // get and store document data from object
urlSafe: object[key].urlSafe
});
})
array.sort((a,b) => (a.name.toLowerCase() > b.name.toLowerCase()) ? 1 : ((b.name.toLowerCase() > a.name.toLowerCase()) ? -1 : 0));
var output = '';
for (let i = 0; i < array.length; i++) {
output += options.fn(array[i]);
}
return output;
});
Here is a full solution that is a solution for the following question (from the original issue):
tag1 (4), tag2 (2), tag3 (10)
tag1
and tag3
would be displayed if x=3.The solution is a new helper that can be used in many ways. I add then 3 ways to call the helper:
{{#each_tags tags "occurencies" 3 1000 true}}
<li><a href="/tags/{{urlSafe}}/" class="badge badge-secondary" aria-label="tag {{name}}">{{name}} ({{occurencies}})</a></li>
{{/each_tags}}
{{#each_tags tags "name" 2 1000 false}}
<li><a href="/tags/{{urlSafe}}/" class="badge badge-secondary" aria-label="tag {{name}}">{{name}} ({{occurencies}})</a></li>
{{/each_tags}}
{{#each_tags tags "name" 1 1 false}}
<li><a href="/tags/{{urlSafe}}/" class="badge badge-secondary" aria-label="tag {{name}}">{{name}}</a></li>
{{/each_tags}}
Handlebars.registerHelper('each_tags', function(object, sortField, minOccurency, maxOccurency, reverse, options) {
var keys = Object.keys(object);
var array = [];
keys.forEach(key => {
if ((object[key].length >= minOccurency) && (object[key].length <= maxOccurency)) {
array.push({
name: key,
urlSafe: object[key].urlSafe,
occurencies: object[key].length
});
}
})
array.sort((a,b) => {
if (typeof a[sortField] === "string") {
return ((a[sortField].toLowerCase() > b[sortField].toLowerCase()) ? 1 : ((b[sortField].toLowerCase() > a[sortField].toLowerCase()) ? -1 : 0));
} else {
return ((a[sortField] > b[sortField]) ? 1 : ((b[sortField] > a[sortField]) ? -1 : 0));
}
});
if (reverse) {
array = array.reverse();
}
var output = '';
for (let i = 0; i < array.length; i++) {
output += options.fn(array[i]);
}
return output;
});
I had to use a helper because the plugin does not evolve anymore.
But I think that the features offered by this helper should be included in the plugin itself.
I have a page that list all the used tags.
tag1 (4), tag2 (2), tag3 (10)
tag1
andtag3
would be displayed if x=3.