Class: Jekyll::Archives::Archives

Inherits:
Generator
  • Object
show all
Defined in:
lib/jekyll-archives.rb

Constant Summary collapse

DATE_ATTRS =
%w[year month day].freeze
LEGACY_ATTRS =

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

{ 'tags' => 'tag', 'categories' => 'category' }.freeze
DEFAULTS =
{
  "layout"     => "archive",
  "group"      => false,
  "enabled"    => [],
  "titles"     => {},
  "replace"    => false,
  "permalinks" => {
    "year"     => "/:year/",
    "month"    => "/:year/:month/",
    "day"      => "/:year/:month/:day/",
    "tag"      => "/tag/:name/",
    "category" => "/category/:name/",
    "category-tag" => "/category/:category/tag/:tag/",
  }
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(config = {}) ⇒ Archives

Returns a new instance of Archives.



35
36
37
38
39
40
41
42
43
44
45
46
# 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

Instance Method Details

#attr_title_enabled?(attr, value) ⇒ Boolean

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

Returns:

  • (Boolean)


93
94
95
96
97
98
99
100
101
# 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

#attrsObject

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



195
196
197
198
199
# File 'lib/jekyll-archives.rb', line 195

def attrs
  return LEGACY_ATTRS.keys unless @enabled.is_a? Array

  @attrs ||= @enabled - DATE_ATTRS
end

#combined?Boolean

Check if we have combined archives

Returns:

  • (Boolean)


212
213
214
# File 'lib/jekyll-archives.rb', line 212

def combined?
  @config['combined'].is_a?(Hash)
end

#days(month_posts) ⇒ Object

Custom ‘post_attr_hash` method for days



227
228
229
# File 'lib/jekyll-archives.rb', line 227

def days(month_posts)
  date_attr_hash(month_posts, "%d")
end

#enabled?(archive) ⇒ Boolean

Checks if archive type is enabled in config

Returns:

  • (Boolean)


202
203
204
# File 'lib/jekyll-archives.rb', line 202

def enabled?(archive)
  @enabled == true || @enabled == "all" || (@enabled.is_a?(Array) && @enabled.include?(archive))
end

#generate(site) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 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?Boolean

Checks if we want grouped archives

Returns:

  • (Boolean)


207
208
209
# File 'lib/jekyll-archives.rb', line 207

def group?
  @config['group']
end

#months(year_posts) ⇒ Object

Custom ‘post_attr_hash` method for months



222
223
224
# File 'lib/jekyll-archives.rb', line 222

def months(year_posts)
  date_attr_hash(year_posts, "%m")
end

#readObject

Read archive data from posts



64
65
66
67
68
69
# File 'lib/jekyll-archives.rb', line 64

def read
  read_combined if combined?
  read_attrs
  read_dates
  read_types if group?
end

#read_attrsObject

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



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# 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_combinedObject

Archive posts by a combination of attributes.



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# 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_datesObject



158
159
160
161
162
163
164
165
166
167
168
# 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_typesObject

Generates Archives by Archive type



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/jekyll-archives.rb', line 171

def read_types
  @config['enabled'].each do |type|
    type = LEGACY_ATTRS[type] if LEGACY_ATTRS[type]
    posts = @site.config['archives'][type]&.map(&:posts)&.flatten&.uniq

    next unless posts

    @archives << Archive.new(@site, type, 'group', posts)
  end

  return unless combined?

  @config['combined'].each do |type, _|
    posts = @site.config['archives'][type]&.map(&:posts)&.flatten&.uniq

    next unless posts

    @archives << Archive.new(@site, type, 'group', posts)
  end
end

#yearsObject

Custom ‘post_attr_hash` method for years



217
218
219
# File 'lib/jekyll-archives.rb', line 217

def years
  date_attr_hash(@posts.docs, "%Y")
end