jekyll_all_collections 0.3.6 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,139 +0,0 @@
1
- require 'jekyll_draft'
2
- require 'jekyll_plugin_logger'
3
- require 'jekyll_plugin_support'
4
- require 'securerandom'
5
-
6
- # See https://stackoverflow.com/a/75389679/553865
7
- class NullBinding < BasicObject
8
- def min_binding
9
- ::Kernel
10
- .instance_method(:binding)
11
- .bind_call(self)
12
- end
13
- end
14
-
15
- # @author Copyright 2020 Michael Slinn
16
- # @license SPDX-License-Identifier: Apache-2.0
17
- module AllCollectionsTag
18
- PLUGIN_NAME = 'all_collections'.freeze
19
- CRITERIA = %w[date destination draft label last_modified last_modified_at path relative_path title type url].freeze
20
- DRAFT_HTML = '<i class="jekyll_draft">Draft</i>'.freeze
21
-
22
- class AllCollectionsTag < JekyllSupport::JekyllTag
23
- include JekyllAllCollectionsVersion
24
-
25
- # Method prescribed by JekyllTag.
26
- # @return [String]
27
- def render_impl
28
- AllCollectionsHooks.compute(@site) unless @site.class.method_defined? :all_collections
29
-
30
- @date_column = @helper.parameter_specified?('date_column') || 'date'
31
- unless %w[date last_modified].include?(@date_column)
32
- # TODO: should this just issue a warning and return instead of dieing?
33
- abort "Error: the date_column attribute must either have value 'date' or 'last_modified', " \
34
- "but '#{@date_column}' was specified"
35
- end
36
- @id = @helper.parameter_specified?('id') || SecureRandom.hex(10)
37
- sort_by_param = @helper.parameter_specified? 'sort_by'
38
- sort_by = (sort_by_param&.delete(' ')&.split(',') if sort_by_param != false) || ['-date']
39
- @heading = @helper.parameter_specified?('heading') || self.class.default_head(sort_by)
40
- sort_lambda_string = self.class.create_lambda_string(sort_by)
41
- @logger.debug do
42
- "#{@page['path']} sort_by_param=#{sort_by_param} " \
43
- "sort_lambda_string = #{sort_lambda_string}\n"
44
- end
45
- sort_lambda = self.class.evaluate sort_lambda_string
46
- generate_output sort_lambda
47
- end
48
-
49
- def self.default_head(sort_by)
50
- criteria = (sort_by.map do |x|
51
- reverse = x.start_with? '-'
52
- criterion = x.delete_prefix('-').capitalize
53
- criterion += reverse ? ' (Newest to Oldest)' : ' (Oldest to Newest)'
54
- criterion
55
- end).join(', ')
56
- "All Posts in All Categories Sorted By #{criteria}"
57
- end
58
-
59
- # Descending sort keys reverse the order of comparison
60
- def self.create_lambda_string(criteria)
61
- criteria_lhs_array = []
62
- criteria_rhs_array = []
63
- verify_sort_by_type(criteria).each do |c|
64
- descending_sort = c.start_with? '-'
65
- c.delete_prefix! '-'
66
- abort("Error: '#{c}' is not a valid sort field. Valid field names are: #{CRITERIA.join ', '}") \
67
- unless CRITERIA.include?(c)
68
- criteria_lhs_array << (descending_sort ? "b.#{c}" : "a.#{c}")
69
- criteria_rhs_array << (descending_sort ? "a.#{c}" : "b.#{c}")
70
- end
71
- # Examples:
72
- # "->(a, b) { [a.last_modified] <=> [b.last_modified] }"
73
- # "->(a, b) { [b.last_modified] <=> [a.last_modified] }" (descending)
74
- # "->(a, b) { [a.last_modified, a.date] <=> [b.last_modified, b.date] }" (descending last_modified, ascending date)
75
- # "->(a, b) { [a.last_modified, b.date] <=> [b.last_modified, a.date] }" (ascending last_modified, descending date)
76
- "->(a, b) { [#{criteria_lhs_array.join(', ')}] <=> [#{criteria_rhs_array.join(', ')}] }"
77
- end
78
-
79
- def self.evaluate(string)
80
- eval string, NullBinding.new.min_binding, __FILE__, __LINE__ # rubocop:disable Security/Eval
81
- end
82
-
83
- def self.verify_sort_by_type(sort_by)
84
- if @sort_by.is_a? Array
85
- sort_by
86
- elsif sort_by.is_a? Enumerable
87
- sort_by.to_a
88
- elsif sort_by.is_a? Date
89
- [sort_by.to_i]
90
- elsif sort_by.is_a? String
91
- [sort_by]
92
- else
93
- abort "Error: sort_by was specified as '#{sort_by}'; it must either be a string or an array of strings"
94
- end
95
- end
96
-
97
- private
98
-
99
- def last_modified_value(post)
100
- @logger.debug do
101
- " post.last_modified='#{post.last_modified}'; " \
102
- "post.last_modified_at='#{post.last_modified_at}'; " \
103
- "@date_column='#{@date_column}'"
104
- end
105
- last_modified = if @date_column == 'last_modified' && post.respond_to?(:last_modified)
106
- post.last_modified
107
- elsif post.respond_to? :last_modified_at
108
- post.last_modified_at
109
- else
110
- post.date
111
- end
112
- last_modified ||= post.date || Date.today
113
- last_modified
114
- end
115
-
116
- def generate_output(sort_lambda)
117
- id = @id.to_s.strip.empty? ? '' : " id='#{@id}'"
118
- heading = @heading.strip.to_s.empty? ? '' : "<h2#{id}>#{@heading}</h2>"
119
- collection = @site.all_collections.sort(&sort_lambda)
120
- <<~END_TEXT
121
- #{heading}
122
- <div class="posts">
123
- #{(collection.map do |post|
124
- last_modified = last_modified_value post
125
- date = last_modified.strftime '%Y-%m-%d'
126
- draft = post.draft ? DRAFT_HTML : ''
127
- href = "<a href='#{post.url}'>#{post.title}</a>"
128
- @logger.debug { " date='#{date}' #{post.title}\n" }
129
- " <span>#{date}</span><span>#{href}#{draft}</span>"
130
- end).join "\n"}
131
- </div>
132
- END_TEXT
133
- rescue ArgumentError => e
134
- warn_short_trace e
135
- end
136
-
137
- JekyllSupport::JekyllPluginHelper.register(self, PLUGIN_NAME)
138
- end
139
- end