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

Generating a post tag based on the post date #316

Closed
danurbanowicz opened this issue Nov 22, 2018 · 6 comments
Closed

Generating a post tag based on the post date #316

danurbanowicz opened this issue Nov 22, 2018 · 6 comments
Labels
education waiting-to-close Issue that is probably resolved, waiting on OP confirmation.

Comments

@danurbanowicz
Copy link

danurbanowicz commented Nov 22, 2018

I am happily using zero-maintenance tag pages but now I'm trying to additionally sort and paginate my posts (calendar events) based on an explicitly set date - and specifically by the month.

For example: I could just add tags: april to the post front matter, and it'd allow me to sort my posts by the april tag, but I was thinking it'd be better if Eleventy could just generate the tag from the post date filter I'm using. Something like:

tags: {{ event.date | monthName }} which would output tags: april

..but alas, we can't use template syntax in front matter data for anything other than the permalink field.

So, how could I generate a tag or array of tags for a post based on post data, such as the date? Or is anyone using a different method to organise their collections by date? 🤔

@edwardhorsford
Copy link
Contributor

edwardhorsford commented Nov 22, 2018

I'm doing essentially what you want using a custom collection. I'm doing it to group by months and by years. You could easily extend to group by day, etc.

My code below:

const moment = require("moment");

function generateDateSet(collection, format){
  let dateSet = new Set();

  collection.getAllSorted().forEach(function(item) {
    if( "date" in item.data ) {

      var tags = item.data.tags;
      if( typeof tags === "string" ) {
        tags = [tags];
      }
      if ( tags && ( tags.includes("_blog") || tags.includes("_photoblog") ) ){
        let itemDate = item.data.date;
        var date = moment(itemDate).format(format);
        dateSet.add(date);
      }     
    }
  });

  return Array.from(dateSet);
}

function getItemsByDate(collection, date, format){

  var result = {};
  result = collection.getAll().filter(function(item) {

      var tags = item.data.tags;

      if( typeof tags === "string" ) {
        tags = [tags];
      }

      if ( tags && ( tags.includes("_blog") || tags.includes("_photoblog") ) ){

        if( !item.data.date ){
          return false;
        }

        var itemDate = item.data.date;
        var itemShortDate = moment(itemDate).format(format);

        return (itemShortDate == date);
      };
      return false;
    });

  result = result.sort(function(a, b) {
    return b.date - a.date;
  });

  return result;
}

const contentByDateString = (collection, format) => {
  var dateSet = {};
  var newSet = new Set();

  dateSet = generateDateSet(collection, format);

  dateSet.forEach(function(date){
    var result = getItemsByDate(collection, date, format)
    newSet[date] = result;
  });

  return [{...newSet}];
}


exports.contentByMonth = collection => {
  return contentByDateString(collection, "YYYY/MM");
}

exports.contentByYear = collection => {
  return contentByDateString(collection, "YYYY");
}

Note, because of #277 I have to return the result wrapped in an array - so when you paginate on these collections you'll need to do something like:

pagination: 
 -data: collections.contentByMonth[0]

@danurbanowicz
Copy link
Author

Thanks for this Ed, it's just given me an idea.

@zachleat
Copy link
Member

Is this okay to close? I do think you want a custom collection for this 👍

@zachleat zachleat added education waiting-to-close Issue that is probably resolved, waiting on OP confirmation. labels Dec 17, 2018
@jvoros
Copy link

jvoros commented Feb 1, 2019

@edwardhorsford I like your solution. How did you make your module exports available as a method on the collections object?

@edwardhorsford
Copy link
Contributor

@jvoros it's not quite method on the collections object.

I'm using eleventy's addCollection method like this:
eleventyConfig.addCollection("contentByMonth", require("./utils/collections/contentByDate").contentByMonth);

This creates a new collection using the function I posted above. I then use this collection to make pages / content.

@darekkay
Copy link

See other solutions in #1284

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
education waiting-to-close Issue that is probably resolved, waiting on OP confirmation.
Projects
None yet
Development

No branches or pull requests

5 participants