middleman / middleman-blog

Blog Engine Extension for Middleman
https://middlemanapp.com
MIT License
326 stars 179 forks source link

How to get links to all calendar/tag pages #374

Open aardvarkk opened 5 years ago

aardvarkk commented 5 years ago

Expected behaviour

Actual behaviour

Additional information

tdreyno commented 5 years ago

Looks like you are right, that data for the full set is never captured or shared with templates:

It kind of happens here: https://github.com/middleman/middleman-blog/blob/master/lib/middleman-blog/paginator.rb#L51-L64

Where would it make sense to share that data? Along side prev_page and next_page variables? I can refactor things to make that possible.

aardvarkk commented 5 years ago

I started to look into making a variable called page_list that would just contain an array of all of the resources. I did find exactly that section of the code that you linked to and that's where I started making changes.

What I managed to do instead was to hack together a helper that would keep wandering through prev_page and next_page until there were none left. So I would keep accessing current_resource.locals['prev_page'] and building up an array as I walked through. It was pretty hacky but it worked without me needing to change any code in middleman-blog.

If this is a pretty fringe request I don't mind if you close it off given that there is a workaround -- it just took me quite a while to try to figure out how I could get a list of all the pages and I felt like other people might also want to do that.

tdreyno commented 5 years ago

That's clever. Can you put your solution code here for future folks searching for this?

aardvarkk commented 5 years ago

Yep -- I should be able to post something tonight. I'll edit this comment with the general idea.

EDIT: Here's the code I promised. It's fairly specific to my perhaps-strange use case, but could probably be extended for other needs. I wanted only one blog article per page, but wanted to list all of the other pages for the given tag/calendar page on each page. That way, you could navigate the tags and calendar pages without losing the context of being interested in a certain calendar range or tag.

Here's the custom helper I made with some helper functions:

module CustomHelpers
  # Add an article as a Hash to the collection
  # I store the title for use as eventual link text and the path for the href
  # I pass the operation to do (either `unshift` or `push` 
  # to either prepend or append to the collection
  def add_article(operation_sym, article, collection, path = nil)
    collection.send(operation_sym, {
      title: article.title,
      path: path
    })
  end

  # Walk from a current resource to the next-oldest
  # The "next page" links to the *previous* article,
  # because articles are sorted descending chronologically
  # The key here is grabbing the next page with `current_resource.locals['next_page']`, then setting
  # that as the next "current_resource" for the recursive call
  def walk_older(current_resource, current_article, articles, collection)
    if prev_article = articles.find { |a| a.date < current_article.date }
      add_article(:push, prev_article, collection, '/' + current_resource.locals['next_page'].path)
      walk_older(current_resource.locals['next_page'], prev_article, articles, collection)
    end
  end

  # Same as above, but walking to newer articles/pages
  def walk_newer(current_resource, current_article, articles, collection)
    if next_article = articles.reverse.find { |a| a.date > current_article.date }
      add_article(:unshift, next_article, collection, '/' + current_resource.locals['prev_page'].path)
      walk_newer(current_resource.locals['prev_page'], next_article, articles, collection)
    end
  end
end

Here's how I use it in the template:

          <% newer = [] %>
          <% walk_newer(current_resource, current_article, articles, newer) %>
          <% older = [] %>
          <% walk_older(current_resource, current_article, articles, older) %>

          <% newer.each do |article| %>
            <li><%= link_to article[:title], article[:path] %></li>
          <% end %>

          <li><%= current_article.title %></li>

          <% older.each do |article| %>
            <li><%= link_to article[:title], article[:path] %></li>
          <% end %>
markets commented 7 months ago

ℹ️ This issue is stale because it has been open for more than 90 days with no activity. It will be closed in 30 days if no further activity occurs. Thank you for your contributions.