Skip to content
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

order tags by alphabetical order #49

Open
oupala opened this issue Sep 14, 2017 · 6 comments
Open

order tags by alphabetical order #49

oupala opened this issue Sep 14, 2017 · 6 comments

Comments

@oupala
Copy link

oupala commented Sep 14, 2017

I have a page that list all the used tags.

  • Is there a way to order tags by alphabetical order?
  • Is there a way to mention how many time this tag is used? For example: tag1 (4), tag2 (2), tag3 (10)
  • Is there to display only tags that a used more than x times? In the example above, only tag1 and tag3 would be displayed if x=3.
@MegaJ
Copy link

MegaJ commented Dec 20, 2017

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?

@oupala
Copy link
Author

oupala commented Mar 2, 2018

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.

@MegaJ
Copy link

MegaJ commented Mar 4, 2018

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>

@oupala
Copy link
Author

oupala commented Apr 10, 2020

I found a partial solution with a helper.

Here is the solution for ordering tags:

  • handlebars template:
{{#each_with_sort tags}}
    <li><a href="/tags/{{urlSafe}}/" class="badge badge-secondary" aria-label="tag {{name}}">{{name}}</a></li>
{{/each_with_sort}}
  • handlebars helper:
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;
});

@oupala
Copy link
Author

oupala commented Apr 15, 2020

Here is a full solution that is a solution for the following question (from the original issue):

  • Is there a way to mention how many time this tag is used? For example: tag1 (4), tag2 (2), tag3 (10)
  • Is there to display only tags that a used more than x times? In the example above, only 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:

  • list tags, ordered by occurencies, where occurency is between 3 and 1000 (almost unlimited), in reverse order (most occurency before):
{{#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}}
  • list tags, ordered by name, where occurency is between 2 and 1000 (almost unlimited), in natural order (alphabetical order):
{{#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}}
  • list tags, ordered by name, where occurency is between 1 and 1 (tags used once only), in natural order (alphabetical order):
{{#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 helper:
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;
});

@oupala
Copy link
Author

oupala commented Apr 15, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants