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.
- checksums.yaml +4 -4
- data/.rubocop.yml +19 -1
- data/CHANGELOG.md +34 -8
- data/README.md +208 -105
- data/jekyll_all_collections.gemspec +11 -14
- data/lib/hooks/a_page.rb +69 -0
- data/lib/hooks/all_collections_hooks.rb +59 -0
- data/lib/hooks/all_files.rb +46 -0
- data/lib/hooks/class_methods.rb +50 -0
- data/lib/jekyll_all_collections/version.rb +1 -1
- data/lib/jekyll_all_collections.rb +14 -2
- data/lib/tag/all_collections_tag.rb +158 -0
- data/lib/util/mslinn_binary_search.rb +152 -0
- data/lib/util/send_chain.rb +58 -0
- data/spec/all_collections_tag/all_collections_tag_sort_spec.rb +1 -0
- data/spec/bsearch_spec.rb +50 -0
- data/spec/date_sort_spec.rb +8 -6
- data/spec/mslinn_binary_search_spec.rb +47 -0
- data/spec/send_chain_spec.rb +72 -0
- data/spec/send_spec.rb +28 -0
- data/spec/sorted_lru_files_spec.rb +82 -0
- data/spec/spec_helper.rb +1 -3
- data/spec/status_persistence.txt +32 -22
- data/spec/testable_spec.rb +38 -0
- metadata +33 -11
- data/lib/all_collections_hooks.rb +0 -118
- data/lib/all_collections_tag.rb +0 -139
data/lib/all_collections_tag.rb
DELETED
@@ -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
|