-
-
Save fastdivision/5890772 to your computer and use it in GitHub Desktop.
# If category is with questions... | |
if self.categories[index.data['category']].select { |post| post.categories[0] == 'questions' }.length != 0 | |
# Specify a unique folder for /categories based on post type. In this case, /questions/categories | |
target_dir = '/' + GenerateCategories.category_dir(self.config['category_question_dir'], category) | |
# Use a unique layout file for this post type. In this case, question_category_index.html | |
index = CategoryIndex.new(self, self.source, target_dir, category, 'question_category_index.html') | |
# Add category page to queue for export | |
if index.render? | |
self.pages << index | |
end | |
end |
def write_category_indexes | |
if self.layouts.key? 'blog_category_index' | |
self.categories.keys.each do |category| | |
next if RESTRICTED_CATEGORIES.include? category | |
self.write_category_index(category) | |
end | |
# Throw an exception if the layout couldn't be found. | |
else | |
throw "No 'category_index' layout found." | |
end | |
end |
module Jekyll | |
class Post | |
alias_method :original_to_liquid, :to_liquid | |
def to_liquid | |
original_to_liquid.deep_merge({ | |
'excerpt' => content.match('<!--more-->') ? content.split('<!--more-->').first : nil | |
}) | |
end | |
end | |
module Filters | |
def mark_excerpt(content) | |
content.gsub('<!--more-->', '<p><span id="more"></span></p>') | |
end | |
end | |
end |
module Jekyll | |
module PostAndCategoryFilter | |
RESTRICTED_CATEGORIES = ['blog', 'questions'] | |
# Returns back all categories related to a primary category | |
# e.g. "blog" or "questions" | |
def filter_categories_by_primary_category(posts) | |
filtered = [] | |
for post in posts | |
for post_category in post.categories | |
filtered.push(post_category) unless RESTRICTED_CATEGORIES.include? post_category | |
end | |
end | |
filtered.sort.uniq | |
end | |
end | |
end | |
Liquid::Template.register_filter(Jekyll::PostAndCategoryFilter) |
module Jekyll | |
class Page | |
attr_accessor :dir | |
end | |
module Generators | |
class Pagination < Generator | |
# This generator is safe from arbitrary code execution. | |
safe true | |
# Generate paginated pages if necessary. | |
# | |
# site - The Site. | |
# | |
# Returns nothing. | |
def generate(site) | |
paginate(site, '/blog/index.html', 'blog') | |
paginate_categories(site, '/blog/categories', 'blog_category_index.html', site.categories['blog']) | |
paginate_categories(site, '/questions/categories', 'question_category_index.html', site.categories['questions']) | |
end | |
# Paginates the blog's posts. Renders the index.html file into paginated | |
# directories, e.g.: page2/index.html, page3/index.html, etc and adds more | |
# site-wide data. | |
# | |
# site - The Site. | |
# page - The index.html Page that requires pagination. | |
# | |
# {"paginator" => { "page" => <Number>, | |
# "per_page" => <Number>, | |
# "posts" => [<Post>], | |
# "total_posts" => <Number>, | |
# "total_pages" => <Number>, | |
# "previous_page" => <Number>, | |
# "next_page" => <Number> }} | |
def paginate(site, page_path, category) | |
all_posts = site.site_payload['site']['categories'][category] | |
page = site.pages.select do |page| | |
path = page.dir + "/" + page.name | |
path == page_path | |
end.first | |
pages = Pager.calculate_pages(all_posts, site.config['custom_paginate'].to_i) | |
(1..pages).each do |num_page| | |
pager = Pager.new(site, num_page, all_posts, pages, page) | |
if num_page > 1 | |
newpage = Page.new(site, site.source, page.dir, page.name) | |
newpage.pager = pager | |
newpage.dir = File.join(page.dir, "page#{num_page}") | |
site.pages << newpage | |
else | |
page.pager = pager | |
end | |
end | |
end | |
def paginate_categories(site, category_path, category_layout, posts) | |
categories = [] | |
restricted_categories = ['blog', 'questions'] | |
for post in posts | |
for post_category in post.categories | |
categories.push(post_category) unless restricted_categories.include? post_category | |
end | |
end | |
categories.sort!.uniq! | |
for category in categories | |
all_posts = site.site_payload['site']['categories'][category] | |
page = site.pages.select do |page| | |
path = page.dir + "/" + page.name | |
path == category_path + "/" + category + "/index.html" | |
end.first | |
pages = Pager.calculate_pages(all_posts, site.config['custom_paginate'].to_i) | |
(1..pages).each do |num_page| | |
pager = Pager.new(site, num_page, all_posts, pages, page) | |
if num_page > 1 | |
newpage = CategoryIndex.new(site, site.source, page.dir, category, category_layout) | |
newpage.pager = pager | |
newpage.dir = File.join(page.dir, "page#{num_page}") | |
site.pages << newpage | |
else | |
page.pager = pager | |
end | |
end | |
end | |
end | |
end | |
end | |
class Pager | |
attr_reader :page, :per_page, :posts, :total_posts, :total_pages, | |
:previous_page, :previous_page_path, :next_page, :next_page_path | |
# Calculate the number of pages. | |
# | |
# all_posts - The Array of all Posts. | |
# per_page - The Integer of entries per page. | |
# | |
# Returns the Integer number of pages. | |
def self.calculate_pages(all_posts, per_page) | |
(all_posts.size.to_f / per_page.to_i).ceil | |
end | |
# Determine if the subdirectories of the two paths are the same relative to source | |
# | |
# source - the site source | |
# page_dir - the directory of the Jekyll::Page | |
# paginate_path - the absolute paginate path (from root of FS) | |
# | |
# Returns whether the subdirectories are the same relative to source | |
def self.in_hierarchy(source, page_dir, paginate_path) | |
return false if paginate_path == File.dirname(paginate_path) | |
return false if paginate_path == Pathname.new(source).parent | |
page_dir == paginate_path || | |
in_hierarchy(source, page_dir, File.dirname(paginate_path)) | |
end | |
# Static: Return the pagination path of the page | |
# | |
# site - the Jekyll::Site object | |
# num_page - the pagination page number | |
# target_page - the page where pagination is occurring | |
# | |
# Returns the pagination path as a string | |
def self.paginate_path(site, num_page, target_page) | |
return nil if num_page.nil? | |
return target_page.url if num_page <= 1 | |
format = site.config['paginate_path'] | |
format = format.sub(':num', num_page.to_s) | |
ensure_leading_slash(format) | |
end | |
# Static: Return a String version of the input which has a leading slash. | |
# If the input already has a forward slash in position zero, it will be | |
# returned unchanged. | |
# | |
# path - a String path | |
# | |
# Returns the path with a leading slash | |
def self.ensure_leading_slash(path) | |
path[0..0] == "/" ? path : "/#{path}" | |
end | |
# Static: Return a String version of the input without a leading slash. | |
# | |
# path - a String path | |
# | |
# Returns the input without the leading slash | |
def self.remove_leading_slash(path) | |
ensure_leading_slash(path)[1..-1] | |
end | |
# Initialize a new Pager. | |
# | |
# config - The Hash configuration of the site. | |
# page - The Integer page number. | |
# all_posts - The Array of all the site's Posts. | |
# num_pages - The Integer number of pages or nil if you'd like the number | |
# of pages calculated. | |
def initialize(site, page, all_posts, num_pages = nil, target_page) | |
@page = page | |
@per_page = site.config['custom_paginate'].to_i | |
@total_pages = num_pages || Pager.calculate_pages(all_posts, @per_page) | |
if @page > @total_pages | |
raise RuntimeError, "page number can't be greater than total pages: #{@page} > #{@total_pages}" | |
end | |
init = (@page - 1) * @per_page | |
offset = (init + @per_page - 1) >= all_posts.size ? all_posts.size : (init + @per_page - 1) | |
@total_posts = all_posts.size | |
@posts = all_posts[init..offset] | |
@previous_page = @page != 1 ? @page - 1 : nil | |
@previous_page_path = Pager.paginate_path(site, @previous_page, target_page) | |
@next_page = @page != @total_pages ? @page + 1 : nil | |
@next_page_path = Pager.paginate_path(site, @next_page, target_page) | |
end | |
# Convert this Pager's data to a Hash suitable for use by Liquid. | |
# | |
# Returns the Hash representation of this Pager. | |
def to_liquid | |
{ | |
'page' => page, | |
'per_page' => per_page, | |
'posts' => posts, | |
'total_posts' => total_posts, | |
'total_pages' => total_pages, | |
'previous_page' => previous_page, | |
'previous_page_path' => previous_page_path, | |
'next_page' => next_page, | |
'next_page_path' => next_page_path | |
} | |
end | |
end | |
end |
def entry(path, date, attrs, site) | |
# Remove the trailing slash from the baseurl if it is present, for consistency. | |
baseurl = site.config['url'] | |
baseurl = baseurl[0..-2] if baseurl=~/\/$/ | |
entry = "\n\t<url>\n\t\t<loc>#{baseurl}#{path}</loc>\n" | |
entry += "\t\t<lastmod>#{date.strftime("%Y-%m-%d")}</lastmod>\n" unless date.nil? | |
entry += attrs.map { |k,v| "\t\t<#{k}>#{v}</#{k}>" }.join("\n") + "\n\t</url>\n" | |
end |
I'm using excerpts with the method. It was already provided by jekyll so I didn't have to use the plugin. Any ideas on how I may remove images from the excerpts?
Hi there. I'm already using the plugin filter_posts_and_categories.rb and it works as intended. Thanks for sharing your plugin code.
Anyway, the generate_pagination.rb plugin seems to be very promising. However, I've tried to set it up but jekyll fails to serve and throws the following error:
generate_pagination.rb:87:in 'block (2 levels) in paginate_categories': undefined method 'pager=' for nil:NilClass (NoMethodError)
I've slightly modified the plugin so that it fits my site / blog set up.
So in config.yml I've place the following:
category_dir: "/blog/categories/"
category_portfolio_dir: "/projects/categories/"
And here's the modified lines in the plugin's code
def generate(site)
paginate(site, '/blog/index.html', 'blog')
paginate_categories(site, '/blog/categories', 'blog_category_index.html', site.categories['blog'])
paginate_categories(site, '/portfolio/categories', 'portfolio_category_index.html', site.categories['projects'])
end
Am I supposed to create blog_category_index.html
and portfolio_category_index.html
or are these .html pages going to be generated by the plugin?
I'd really appreciate any thoughts regarding this issue. I would be great if Jekyll paginator could filter posts by type or category.
got the same error as @circa1977
undefined method pager=' for nil:NilClass