class Jekyll::Archives::Archives

Constants

DATE_ATTRS
DEFAULTS
LEGACY_ATTRS

Map between the front matter attribute and names used by jekyll-archive

Public Class Methods

new(config = {}) click to toggle source
# File lib/jekyll-archives.rb, line 35
def initialize(config = {})
  archives_config = config.fetch("jekyll-archives", {})
  if archives_config.is_a?(Hash)
    @config = Utils.deep_merge_hashes(DEFAULTS, archives_config)
  else
    @config = nil
    Jekyll.logger.warn "Archives:", "Expected a hash but got #{archives_config.inspect}"
    Jekyll.logger.warn "", "Archives will not be generated for this site."
  end
  @enabled = @config && @config["enabled"]
  @post_attr_hash = {}
end

Public Instance Methods

attr_title_enabled?(attr, value) click to toggle source

If the permalink is a hash of value => template, check if it isn't disabled.

# File lib/jekyll-archives.rb, line 93
def attr_title_enabled?(attr, value)
  permalinks = @config.dig('permalinks', attr)

  if permalinks.is_a?(Hash)
    !!permalinks.dig(value)
  else
    true
  end
end
attrs() click to toggle source

Return the front matter attributes to archive by, using the legacy names unless specified and leaving out the date attributes.

# File lib/jekyll-archives.rb, line 188
def attrs
  return LEGACY_ATTRS.keys unless @enabled.is_a? Array

  @attrs ||= @enabled - DATE_ATTRS
end
combined?() click to toggle source

Check if we have combined archives

# File lib/jekyll-archives.rb, line 205
def combined?
  @config['combined'].is_a?(Hash)
end
days(month_posts) click to toggle source

Custom `post_attr_hash` method for days

# File lib/jekyll-archives.rb, line 220
def days(month_posts)
  date_attr_hash(month_posts, "%d")
end
enabled?(archive) click to toggle source

Checks if archive type is enabled in config

# File lib/jekyll-archives.rb, line 195
def enabled?(archive)
  @enabled == true || @enabled == "all" || (@enabled.is_a?(Array) && @enabled.include?(archive))
end
generate(site) click to toggle source
# File lib/jekyll-archives.rb, line 48
def generate(site)
  return if @config.nil?

  @site = site
  @posts = site.posts
  @archives = []

  @site.config["jekyll-archives"] = @config

  read
  @site.pages.concat(@archives)

  @site.config["archives"] = @archives unless group?
end
group?() click to toggle source

Checks if we want grouped archives

# File lib/jekyll-archives.rb, line 200
def group?
  @config['group']
end
months(year_posts) click to toggle source

Custom `post_attr_hash` method for months

# File lib/jekyll-archives.rb, line 215
def months(year_posts)
  date_attr_hash(year_posts, "%m")
end
read() click to toggle source

Read archive data from posts

# File lib/jekyll-archives.rb, line 64
def read
  read_combined if combined?
  read_attrs
  read_dates
  read_types if group?
end
read_attrs() click to toggle source

Read and group by attributes, using the legacy names when needed.

# File lib/jekyll-archives.rb, line 73
def read_attrs
  attrs.each do |attr|
    post_attr_hash(attr).each do |title, posts|
      attr = LEGACY_ATTRS[attr] if LEGACY_ATTRS[attr]

      next unless attr_title_enabled? attr, title

      @archives << Archive.new(@site, title, attr, posts)

      next unless group?

      @site.config['archives'] ||= {}
      @site.config['archives'][attr] ||= []
      @site.config['archives'][attr] << @archives.last
    end
  end
end
read_combined() click to toggle source

Archive posts by a combination of attributes.

# File lib/jekyll-archives.rb, line 104
def read_combined
  # We can have many combination archives
  @config['combined'].each do |type, combined|
    # This is an empty map so we can have all keys on the result
    empty_combination = Hash[combined.map{|k| [k,nil]}]

    # We collect all posts
    @posts.docs.map do |post|
      # Array of Jekyll::Document and Hash of values, some may be
      # empty.
      [ post, empty_combination.merge(**post.data.slice(*combined)) ]
    end.select do |combination|
      # We skip Documents that don't have any of the attributes
      combination.last.none? do |_, e|
        # TODO: Move to its own method
        e.nil? || (e.respond_to?(:empty?) && e.empty?) || (e.respond_to?(:blank?) && e.blank?) || (e.respond_to?(:zero?) && e.zero?)
      end
    end.map do |post, data|
      # Since the values can be Arrays, we'll generate all
      # combinations
      data.values.reduce do |memo, value|
        # XXX: Ensure value is an Array, it could be a String or other
        # value.
        (memo.is_a?(Array) ? memo : [memo]).product([value].flatten)
      end.map(&:flatten).map do |v|
        # Recreate a Hash of attribute and single value for each
        # combination
        data.keys.zip(v)
      end.map do |hash|
        # Recreate the first collection of Document and Hash for
        # each combination.
        [ post, Hash[hash] ]
      end
    end.flatten(1).group_by(&:last).transform_values(&:flatten).transform_values do |v|
      # Create groups by value combinations and select only
      # Documents
      v.select do |p|
        p.is_a? Jekyll::Document
      end
    end.each do |combination, posts|
      # Then create Archives for them.
      archive = Archive.new(@site, combination, type, posts)

      @archives << archive

      next unless group?

      @site.config['archives'] ||= {}
      @site.config['archives'][type] ||= []
      @site.config['archives'][type] << archive
    end
  end
end
read_dates() click to toggle source
# File lib/jekyll-archives.rb, line 158
def read_dates
  years.each do |year, y_posts|
    append_enabled_date_type({ :year => year }, "year", y_posts)
    months(y_posts).each do |month, m_posts|
      append_enabled_date_type({ :year => year, :month => month }, "month", m_posts)
      days(m_posts).each do |day, d_posts|
        append_enabled_date_type({ :year => year, :month => month, :day => day }, "day", d_posts)
      end
    end
  end
end
read_types() click to toggle source

Generates Archives by Archive type

# File lib/jekyll-archives.rb, line 171
def read_types
  @config['enabled'].each do |type|
    type = LEGACY_ATTRS[type] if LEGACY_ATTRS[type]

    @archives << Archive.new(@site, type, 'group', @site.config['archives'][type].map(&:posts).flatten.uniq)
  end

  return unless combined?

  @config['combined'].each do |type, _|
    @archives << Archive.new(@site, type, 'group', @site.config['archives'][type].map(&:posts).flatten.uniq)
  end
end
years() click to toggle source

Custom `post_attr_hash` method for years

# File lib/jekyll-archives.rb, line 210
def years
  date_attr_hash(@posts.docs, "%Y")
end

Private Instance Methods

append_enabled_date_type(meta, type, posts) click to toggle source

Initialize a new Archive page and append to base array if the associated date `type` has been enabled by configuration.

meta - A Hash of the year / month / day as applicable for date. type - The type of date archive. posts - The array of posts that belong in the date archive.

# File lib/jekyll-archives.rb, line 232
def append_enabled_date_type(meta, type, posts)
  @archives << Archive.new(@site, meta, type, posts) if enabled?(type)
end
date_attr_hash(posts, id) click to toggle source

Custom `post_attr_hash` for date type archives.

posts - Array of posts to be considered for archiving. id - String used to format post date via `Time.strptime` e.g. %Y, %m, etc.

# File lib/jekyll-archives.rb, line 240
def date_attr_hash(posts, id)
  hash = Hash.new { |hsh, key| hsh[key] = [] }
  posts.each { |post| hash[post.date.strftime(id)] << post }
  hash.each_value { |posts| posts.sort!.reverse! }
  hash
end
post_attr_hash(post_attr) click to toggle source

Custom `post_attr_hash` to group by any attribute

# File lib/jekyll-archives.rb, line 248
def post_attr_hash(post_attr)
  @post_attr_hash[post_attr] ||= begin
    hash = Hash.new { |h, key| h[key] = [] }
    @site.posts.docs.each do |p|
      d = p.data[post_attr]

      next if d.nil?

      if d.respond_to? :each
        d.each { |t| hash[t] << p }
      else
        hash[d.to_s] << p
      end
    end
    hash.each_value { |posts| posts.sort!.reverse! }
    hash
  end
end