-
-
Notifications
You must be signed in to change notification settings - Fork 518
Collection of Tags #927
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I'm looking to get an array of tags that I can then iterate over and then use |
@richardherbert Possibly this? https://www.11ty.dev/docs/quicktips/tag-pages/ |
Thanks @pdehaan I hadn't found that page. On the surface using
In fact using I don't seem to be able to access the objects in the array? |
Sorry, I don't know Liquid (I'm generally a Nunjucks guy), but it looks like you're finding 8 tags/collections, based on your loop output above. |
Yes, I tried dumping |
A little strange. I'm not sure why it's looping if it isn't finding anything. If you have the code in GitHub or similar, I can try pulling the repo and taking a quick look. |
I did get a bit closer on this (using Nunjucks still though, haven't tried w/ Liquid). But here's my Nunjucks file: {# eleventyConfig.addFilter("keys", obj => Object.keys(obj)); #}
<p>{{ collections | keys | dump(2) | safe }}</p>
<section>
{%- for tag, posts in collections %}
tag: {{ tag }}, posts: {{ posts | length }}<br/>
{%- endfor %}
</section>
<hr>
<section>
{%- for tag2, posts2 in collections | dictsort %}
tag: {{ tag2 }}, posts: {{ posts2 | length }};<br/>
{%- endfor %}
</section> Where the custom eleventyConfig.addFilter("keys", obj => Object.keys(obj)); And the output is: <p>[ 'all', 'page', 'contact', 'post', 'about' ]</p>
<section>
tag: all, posts: 7<br/>
tag: page, posts: 2<br/>
tag: contact, posts: 1<br/>
tag: post, posts: 2<br/>
tag: about, posts: 1<br/>
</section>
<hr>
<section>
tag: about, posts: 1;<br/>
tag: all, posts: 7;<br/>
tag: contact, posts: 1;<br/>
tag: page, posts: 2;<br/>
tag: post, posts: 2;<br/>
</section> The one interesting thing about the output, is that it seems like the tag order isn't guaranteed. Each time I regenerated the site, the order of the keys was slightly different. So if you want a specific sorting (ie: sort by number of posts descending), you might need to get a bit creative. Sorting alphabetically is probably trivial since you could probably just do: <p>{{ collections | keys | sort }}</p> I can also try cleaning up my repo and push it to GitHub if that'd help. I started with that, and then for some reason got distracted and started porting all the built-in Liquid filters so they'd work with Nunjucks. |
That's a good lead, thanks. I'll try and translate that into Liquid and knock up a sample repo. I did think I'd have to drop into JavaScript, not one of my core skills, to write a filter but I was hoping that the issue was me not being about to find the right page in the documentation, being new to this project. Like you, I'm spinning several project plates atm so I will get back to you later. |
This issue provides some interesting input. I am looking for a similar thing.
or
What I came up with:
Probably not the fastest approach but reasonable flexible. |
Excuse me ignorance @tcurdt but I don't understand what youe |
@richardherbert all the tags of the pages passed into the filter. I use the same pattern for my post archive. Maybe that helps to make it clear:
|
I'm currently using this code, and am wondering how to sort it alphabetically. Haven't yet found anything in nunjucks documentation:
|
@dixonge I'm trying to do this with Liquid, which I didn't make clear at the start, and there doesn't seem to be anything like |
Simply what I'm trying to do is get an array of content objects grouped by tags that I can iterate over and display. |
You could create another custom filter which removes unwanted items from an array. I randomly chose to convert to a eleventyConfig.addFilter("keys", obj => Object.keys(obj));
eleventyConfig.addFilter("except", (arr=[], ...values) => {
const data = new Set(arr);
for (const item of values) {
data.delete(item);
}
return [...data].sort();
}); And if you're using liquid, you could use the filters like this: {{ collections | keys | except "all", "Home", "About", "Legal" }} |
@dixonge: Nunjucks has a built-in https://mozilla.github.io/nunjucks/templating.html#sort-arr-reverse-casesens-attr sort(arr=[], reverse=false, caseSens=false, attr=undefined) <ol>
{% for tag in collections.tagList | sort %}
<li> {% set tagUrl %}/tags/{{ tag }}/{% endset %}
<a href="{{ tagUrl | url }}" class="tag">{{ tag | title }}</a>
</li>
{% endfor %}
</ol> If {% for tag in collections.tagList | sort(false, false, "objectPropToSortBy") %} |
Wow, that was it! Thank you! I had seen a reference to that, but no good examples for usage I could wrap my brain around. |
@dixonge Yeah, I had to dig into the Nunjucks source to try and figure it out. |
@pdehaan @dixonge Thank you for your thoughts. So after much thrashing around, Googling, trial and error I think I have a Liquid working solution! In my
...then in my md page...
...gives me... Result! Any suggestions to tighten this up would be more than welcome! |
sorry if I'm interrupting, but I've noticed the eleventy-base-blog achieves something similar by creating a custom collection: https://github.com/11ty/eleventy-base-blog/blob/master/_11ty/getTagList.js Dunno if that was what you were looking for. |
@ThePeach - Thanks, I'll take a look at that. |
just referencing @ThePeach suggestion with little improving (less code and sorting) you could include the code bellow in your eleventy config
and access it in your templates:
|
Adds a new collection of tags, excluding `all` from the collection. Solution was sourced from [here](11ty/eleventy#927 (comment)) which is based on [tags.njk](https://github.com/11ty/eleventy-base-blog/blob/1148b90e22851df01be3f6b8b9ee6522c0b0566b/tags.njk ) The collections created for the `CV` section have been prepended with `cv_`. This prevents a name clash with blog tags, where `awards` was used in both sections of the site.
Slight refinement over @joaomelo's contribution. When doing list data processing, I like to reduce the operations to a series of functional programming calls if I can. eleventyConfig.addCollection('tagList', collections => {
const tags = collections
.getAll()
.reduce((tags, item) => tags.concat(item.data.tags), [])
.filter(tag => !!tag)
.filter(tag => tag !== 'post')
.sort();
return Array.from(new Set(tags))
}); |
@TrentonAdams that's working for me, thanks. Now I need to refine it so the tagList collection only lists tags found within collections.page and not from collections.all. I've tried various things but I can't get it to work. Please could you suggest a way? |
@nigelwhite I'm not at my other computer at the moment, but couldn't you just use collections.page instead of collections.all, and that would ensure what you speak of? |
Thanks @TrentonAdams. Yes, that's what I thought too. So, in eleventy.js, I tried eleventyConfig.addCollection('tagMenu', (collections) => {
const tags = collections
.getAll(collections.page)
.reduce((tags, item) => tags.concat(item.data.tags), [])
.filter((tag) => !!tag)
.filter((tag) => tag !== 'page')
.sort();
return Array.from(new Set(tags));
}); but the resulting tag list still includes tags found only in my other content type which is collections.post. |
@nigelwhite I don't think that's correct. As far as I can tell, https://www.11ty.dev/docs/collections/#getall() eleventy/src/TemplateCollection.js Lines 14 to 16 in 094c985
UPDATE: Possibly something like this: eleventyConfig.addCollection("pageTags", (collections) => {
const uniqueTags = collections
.getFilteredByTag("page")
.reduce((tags, item) => tags.concat(...item.data.tags), [])
// Tags to ignore...
.filter(tag => !!tag && !["page", "post"].includes(tag))
.sort();
// Dedupe tags
return Array.from(new Set(uniqueTags));
}); |
@nigelwhite I was thinking more along the lines of replacing |
Okay, I was finally able to take a look. collections.page doesn't exist, so I'm not sure what you're referring to @nigelwhite. Did you create a collection of your own called "page"? If so, only you would know how to do what you ask. If the "page" collections is a simple array of tags then you should just be able to add another filter that checks if the "page" collection "includes" said tag. If "page" is a tag you've been using, then I'd just add the line that pdehaan mentioned... .filter(tag => !!tag && !["page", "post"].includes(tag) |
Thanks @TrentonAdams and @pdehaan. Yes 'page' and 'post' are two tags that I've been adding in my markdown files. I wanted to use these as an 11ty-style way of having 2 content types on my site. So every .md file has either the 'page' or the 'post' tag - never both. They are also stored in differnt folders, but it seems collections ignores folders so that doesn't help. Your solution worked, thanks. This is the code that works eleventyConfig.addCollection('pageTags', (collections) => {
const uniqueTags = collections
.getFilteredByTag('page')
.reduce((tags, item) => tags.concat(item.data.tags), [])
.filter((tag) => !!tag)
.filter((tag) => !!tag && !['page', 'post'].includes(tag))
.sort();
return Array.from(new Set(uniqueTags));
}); |
if in need of taglist + count posts this can be done (based on everyone else answer of course! eleventyConfig
.addFilter('postTags', tags => Object.keys(tags)
.filter(k => k !== "posts")
.filter(k => k !== "all")
.map(k => ({name: k, count: tags[k].length}))
.sort((a,b) => b.count - a.count)); enables something like this on templates: <div style="display: flex; flex-wrap: wrap;">
{% assign tagList = collections | postTags %}
{%- for tag in tagList -%}
<a href="/tag/{{tag.name}}">{{tag.name}}({{tag.count}})</a>
{%- endfor -%}
</div> |
How can I find all the tags used by all my content?
The text was updated successfully, but these errors were encountered: