jekyll_plugin_support 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +21 -2
- data/CHANGELOG.md +13 -0
- data/README.md +50 -8
- data/jekyll_plugin_support.gemspec +1 -0
- data/lib/block/jekyll_plugin_support_block.rb +3 -2
- data/lib/block/jekyll_plugin_support_block_noarg.rb +1 -1
- data/lib/error/jekyll_custom_error.rb +6 -5
- data/lib/hooks/a_page.rb +184 -50
- data/lib/hooks/all_collections_hooks.rb +8 -8
- data/lib/hooks/class_methods.rb +5 -17
- data/lib/jekyll_all_collections/all_collections_tag.rb +66 -49
- data/lib/jekyll_plugin_support/jekyll_plugin_support_class.rb +3 -2
- data/lib/jekyll_plugin_support/version.rb +1 -1
- data/lib/jekyll_plugin_support.rb +10 -0
- data/spec/all_collections_tag/all_collections_tag_sort_spec.rb +147 -75
- data/spec/custom_error_spec.rb +4 -2
- data/spec/jekyll_plugin_helper_options_spec.rb +2 -0
- data/spec/liquid_variable_parsing_spec.rb +1 -0
- data/spec/spec_helper.rb +13 -3
- data/spec/status_persistence.txt +6 -3
- data/spec/testable_spec.rb +9 -9
- metadata +17 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c20bec384d298ac931d132f59dbcaf621e9f55440954dc8c6579b1c9131df62e
|
4
|
+
data.tar.gz: 4cfd22137529da35c52f788ab70ec81fe9457d6b533ec5bc70f653b22791db0e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eafd8b44d05e23011bd30a2bb3bab69befb3cd90b520585d4cf05d164b1b2c76a5218cdd0bdbf3bc7ba6f9a25e789f171403f3553d2cb68d13e0c54346d69b5e
|
7
|
+
data.tar.gz: 1beb29113474e1d501d5394b90288f7e46047e846b868df80f1a5afe9287ae7eece17e7d00e95e9443b7d3b2a69d6d93d9c27d0f6d81d1f4d2f0afba8ae152fe
|
data/.rubocop.yml
CHANGED
@@ -48,9 +48,10 @@ Metrics/BlockLength:
|
|
48
48
|
Metrics/ClassLength:
|
49
49
|
Exclude:
|
50
50
|
- "**/all_collections_tag.rb"
|
51
|
+
Max: 150
|
51
52
|
|
52
53
|
Metrics/CyclomaticComplexity:
|
53
|
-
Max:
|
54
|
+
Max: 35
|
54
55
|
|
55
56
|
Metrics/MethodLength:
|
56
57
|
Max: 50
|
@@ -60,7 +61,7 @@ Metrics/ModuleLength:
|
|
60
61
|
- "**/jekyll_plugin_support_class.rb"
|
61
62
|
|
62
63
|
Metrics/PerceivedComplexity:
|
63
|
-
Max:
|
64
|
+
Max: 35
|
64
65
|
|
65
66
|
Naming/FileName:
|
66
67
|
Exclude:
|
@@ -70,6 +71,9 @@ Naming/FileName:
|
|
70
71
|
RSpec/ExampleLength:
|
71
72
|
Max: 30
|
72
73
|
|
74
|
+
RSpec/MultipleMemoizedHelpers:
|
75
|
+
Enabled: false
|
76
|
+
|
73
77
|
RSpec/SpecFilePathFormat:
|
74
78
|
Enabled: false
|
75
79
|
IgnoreMethods: true
|
@@ -83,6 +87,13 @@ RSpec/IndexedLet:
|
|
83
87
|
RSpec/MultipleExpectations:
|
84
88
|
Max: 15
|
85
89
|
|
90
|
+
RSpec/MultipleDescribes:
|
91
|
+
Enabled: false
|
92
|
+
|
93
|
+
Security/Eval:
|
94
|
+
Exclude:
|
95
|
+
- spec/all_collections_tag/all_collections_tag_sort_spec.rb
|
96
|
+
|
86
97
|
Style/ClassVars:
|
87
98
|
Enabled: false
|
88
99
|
|
@@ -92,8 +103,16 @@ Style/Documentation:
|
|
92
103
|
Style/FrozenStringLiteralComment:
|
93
104
|
Enabled: false
|
94
105
|
|
106
|
+
Style/GlobalVars:
|
107
|
+
Exclude:
|
108
|
+
- spec/mslinn_binary_search_spec.rb
|
109
|
+
|
95
110
|
Style/StringConcatenation:
|
96
111
|
Enabled: false
|
97
112
|
|
113
|
+
Style/StringLiterals:
|
114
|
+
Exclude:
|
115
|
+
- spec/all_collections_tag/all_collections_tag_sort_spec.rb
|
116
|
+
|
98
117
|
Style/TrailingCommaInHashLiteral:
|
99
118
|
EnforcedStyleForMultiline: comma
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 3.1.0 / 2025-06-10
|
4
|
+
|
5
|
+
* Added attribute `order` and method `field` to support `jekyll_outline`.
|
6
|
+
* Added another constructor for `AllCollectionsHooks::APage`, called `apage_from`.
|
7
|
+
* Added new method `new_attribute` to module `JekyllSupport`.
|
8
|
+
* The displayed date field (`:date` or `:last_modified`) now defaults to the primary sort field.
|
9
|
+
* Modified specs tests.
|
10
|
+
* Jekyll tag `AllCollectionsTag` now accepts an optional parameter called
|
11
|
+
`collection_name`, which filters the selected data source. A warning is logged
|
12
|
+
if the data source is anything but `all_collections`.
|
13
|
+
* Moved `APage` and its constructors to the `JekyllCollections` module.
|
14
|
+
|
15
|
+
|
3
16
|
## 3.0.0 / 2025-02-09
|
4
17
|
|
5
18
|
* Numbered as v3.0.0 because `jekyll_draft` was at v2.1.0 and the two projects should have similar version numbers.
|
data/README.md
CHANGED
@@ -64,6 +64,10 @@ Jekyll plugin tags created from `jekyll_plugin_support` framework automatically
|
|
64
64
|
|
65
65
|
d. `sorted_lru_files` is used by a new binary search lookup for matching page suffixes.
|
66
66
|
The `jekyll_href` and `jekyll_draft` plugins use this feature.
|
67
|
+
17. A new Ruby class, `APage`, which abstracts all URL-addressable entities in a Jekyll website.
|
68
|
+
An `APage` can be constructed from a Jekyll `Document` or `Page`, a static file, and a Ruby hash.
|
69
|
+
|
70
|
+
`APage` instances can help immensely when automating content generation and reporting tasks.
|
67
71
|
|
68
72
|
## Installation
|
69
73
|
|
@@ -76,7 +80,7 @@ add the following line to your Jekyll plugin’s `Gemfile`.
|
|
76
80
|
```ruby
|
77
81
|
group :jekyll_plugins do
|
78
82
|
# ...
|
79
|
-
gem 'jekyll_plugin_support', '>=
|
83
|
+
gem 'jekyll_plugin_support', '>= 3.1.0'
|
80
84
|
# ...
|
81
85
|
end
|
82
86
|
```
|
@@ -95,7 +99,7 @@ If your custom plugin will be packaged into a gem, add the following to your plu
|
|
95
99
|
```ruby
|
96
100
|
Gem::Specification.new do |spec|
|
97
101
|
# ...
|
98
|
-
spec.add_dependency 'jekyll_plugin_support', '>=
|
102
|
+
spec.add_dependency 'jekyll_plugin_support', '>= 3.1.0'
|
99
103
|
# ...
|
100
104
|
end
|
101
105
|
```
|
@@ -235,13 +239,28 @@ The general form of the Jekyll tag, including all options, is:
|
|
235
239
|
|
236
240
|
```html
|
237
241
|
{% all_collections
|
242
|
+
collection_name='posts'
|
243
|
+
data_selector='all_collections'
|
238
244
|
date_column='date|last_modified'
|
239
245
|
heading='All Posts'
|
240
|
-
id='
|
246
|
+
id='post_outline'
|
241
247
|
sort_by='SORT_KEYS'
|
242
248
|
%}
|
243
249
|
```
|
244
250
|
|
251
|
+
Each of these attributes are explained below.
|
252
|
+
|
253
|
+
|
254
|
+
#### `collection_name` Attribute
|
255
|
+
|
256
|
+
Name of the collection that this `APage` belongs to, or `nil`.
|
257
|
+
|
258
|
+
|
259
|
+
##### `data_selector` Attribute
|
260
|
+
|
261
|
+
Name of the data collection to work from, defaults to `all_collections`.
|
262
|
+
Other allowable values are `all_documents` and `everything`.
|
263
|
+
|
245
264
|
|
246
265
|
##### `date_column` Attribute
|
247
266
|
|
@@ -1005,17 +1024,35 @@ The `site.all_collections`, `site.all_documents` and `site.everything` attribute
|
|
1005
1024
|
consist of arrays of [`APage`](lib/hooks/a_page.rb) instances.
|
1006
1025
|
|
1007
1026
|
The `APage` class has the following attributes:
|
1008
|
-
`content` (HTML or Markdown), `data` (array), `date` (Ruby Date), `description`, `destination`,
|
1009
|
-
`draft` (Boolean), `ext`, `href`, `label`, `last_modified` or `last_modified_at` (Ruby Date),
|
1010
|
-
`layout`, `origin`, `path`, `relative_path`, `tags`, `title`, `type`, and `url`.
|
1011
1027
|
|
1028
|
+
* `content` (HTML or Markdown)
|
1029
|
+
* `collection_name`
|
1030
|
+
* `content` (HTML or Markdown)
|
1031
|
+
* `data` (array)
|
1032
|
+
* `date` (Ruby Date)
|
1033
|
+
* `description`
|
1034
|
+
* `destination`,
|
1035
|
+
* `draft` (Boolean)
|
1036
|
+
* `ext` / `extname`
|
1012
1037
|
* `href` always starts with a slash.
|
1013
|
-
This value is consistent with
|
1038
|
+
This value is consistent with a `href` values in website HTML.
|
1014
1039
|
Paths ending with a slash (`/`) have `index.html` appended so the path specifies an actual file.
|
1015
|
-
|
1040
|
+
* `label`
|
1041
|
+
* `last_modified` (Ruby Date)
|
1042
|
+
* `last_modified_field` indicates the name of the field that originally contained the value for
|
1043
|
+
`last_modified` (`last_modified` or `last_modified_at`)
|
1044
|
+
* `layout`
|
1045
|
+
* `logger` helpful for error handling
|
1046
|
+
* `name`
|
1016
1047
|
* `origin` indicates the original source of the item.
|
1017
1048
|
Possible values are `collection`, `individual_page` and `static_file`.
|
1018
1049
|
Knowing the origin of each item allows code to process each type of item appropriately.
|
1050
|
+
* `path`
|
1051
|
+
* `relative_path`
|
1052
|
+
* `tags`
|
1053
|
+
* `title`
|
1054
|
+
* `type`
|
1055
|
+
* `url`
|
1019
1056
|
|
1020
1057
|
|
1021
1058
|
## `all_collections` Block Tag
|
@@ -1025,6 +1062,11 @@ The ordering is configurable; by default, the listing is sorted by `date`, newes
|
|
1025
1062
|
The `all_collections` tag has a `data_source` parameter that specifies which new property to report on
|
1026
1063
|
(`all_collections`, `all_documents`, or `everything`).
|
1027
1064
|
|
1065
|
+
For an example of how to use this Jekyll tag in conjunction with the
|
1066
|
+
[jekyll_outline](http://localhost:4001/jekyll_plugins/jekyll_outline.html) tag,
|
1067
|
+
see the [outline_tabs](http://localhost:4001/jekyll_plugins/jekyll_outline.html#outline_tabs)
|
1068
|
+
section of the jekyll_outline documentation.
|
1069
|
+
|
1028
1070
|
|
1029
1071
|
## Requirements
|
1030
1072
|
|
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.test_files = spec.files.grep %r{^(test|spec|features)/}
|
30
30
|
spec.version = JekyllPluginSupportVersion::VERSION
|
31
31
|
|
32
|
+
spec.add_dependency 'bigdecimal'
|
32
33
|
spec.add_dependency 'facets'
|
33
34
|
spec.add_dependency 'jekyll', '>= 4.4.1'
|
34
35
|
spec.add_dependency 'jekyll_plugin_logger'
|
@@ -45,7 +45,7 @@ module JekyllSupport
|
|
45
45
|
# Method prescribed by the Jekyll plugin lifecycle.
|
46
46
|
# Defines @config, @envs, @mode, @page and @site
|
47
47
|
# @return [String]
|
48
|
-
def render(liquid_context)
|
48
|
+
def render(liquid_context) # rubocop: disable Metrics/AbcSize
|
49
49
|
@helper.liquid_context = ::JekyllSupport.inject_config_vars liquid_context # modifies liquid_context
|
50
50
|
text = super # Liquid variable values in content are looked up and substituted
|
51
51
|
|
@@ -82,10 +82,11 @@ module JekyllSupport
|
|
82
82
|
render_impl(text)
|
83
83
|
rescue StandardError => e
|
84
84
|
e.shorten_backtrace
|
85
|
+
@logger.error e.full_message
|
85
86
|
file_name = e.backtrace[0]&.split(':')&.first
|
86
87
|
in_file_name = "in '#{file_name}' " if file_name
|
87
88
|
of_page = "of '#{@page['path']}'" if @page
|
88
|
-
@logger.error { "
|
89
|
+
@logger.error { "While processing line #{@line_number} #{of_page} for #{tag_name} #{in_file_name}- #{e.message}" }
|
89
90
|
binding.pry if @pry_on_standard_error # rubocop:disable Lint/Debugger
|
90
91
|
raise e if @die_on_standard_error
|
91
92
|
|
@@ -12,7 +12,7 @@ module JekyllSupport
|
|
12
12
|
rescue StandardError => e
|
13
13
|
e.shorten_backtrace
|
14
14
|
@logger.error { e.full_message }
|
15
|
-
JekyllSupport.error_short_trace(@logger, e)
|
15
|
+
::JekyllSupport.error_short_trace(@logger, e)
|
16
16
|
end
|
17
17
|
|
18
18
|
# Liquid::Block subclasses do not render if there is no content within the tag
|
@@ -42,11 +42,12 @@ module JekyllSupport
|
|
42
42
|
END_MSG
|
43
43
|
end
|
44
44
|
|
45
|
-
def shorten_backtrace(backtrace_element_count =
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
45
|
+
def shorten_backtrace(backtrace_element_count = 6)
|
46
|
+
set_backtrace backtrace[0..backtrace_element_count]
|
47
|
+
# b = backtrace[0..backtrace_element_count - 1].map do |x|
|
48
|
+
# x.gsub(Dir.pwd + '/', './')
|
49
|
+
# end
|
50
|
+
# set_backtrace b
|
50
51
|
end
|
51
52
|
end
|
52
53
|
end
|
data/lib/hooks/a_page.rb
CHANGED
@@ -1,27 +1,138 @@
|
|
1
|
-
|
1
|
+
require 'date'
|
2
|
+
require 'jekyll_draft'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
module JekyllSupport
|
6
|
+
# Contructor for testing and jekyll_outline
|
7
|
+
def self.apage_from( # rubocop:disable Metrics/ParameterLists
|
8
|
+
collection_name: nil,
|
9
|
+
date: nil,
|
10
|
+
description: nil,
|
11
|
+
draft: false,
|
12
|
+
last_modified: nil,
|
13
|
+
logger: nil,
|
14
|
+
order: nil,
|
15
|
+
title: nil,
|
16
|
+
url: nil
|
17
|
+
)
|
18
|
+
# Jekyll documents have inconsistent date and last_modified property types.
|
19
|
+
date = Time.parse(date) if date.instance_of?(String)
|
20
|
+
unless date.instance_of? Time
|
21
|
+
logger.error { "date is not an instance of Time, it is an instance of #{date.class}" }
|
22
|
+
exit 2
|
23
|
+
end
|
24
|
+
|
25
|
+
last_modified = Date.parse(last_modified) if last_modified.instance_of?(String)
|
26
|
+
last_modified = Date.parse(date.strftime('%Y-%m-%d')) if last_modified.nil?
|
27
|
+
unless last_modified.instance_of? Date
|
28
|
+
logger.error { "last_modified is not an instance of Date, it is an instance of #{last_modified.class}" }
|
29
|
+
exit 3
|
30
|
+
end
|
31
|
+
last_modified = Date.parse(date._to_s) if last_modified.nil?
|
32
|
+
data = {
|
33
|
+
collection: { label: collection_name },
|
34
|
+
draft: draft,
|
35
|
+
last_modified: last_modified,
|
36
|
+
order: order,
|
37
|
+
title: title,
|
38
|
+
}
|
39
|
+
obj = {}
|
40
|
+
JekyllSupport.new_attribute obj, :data, data
|
41
|
+
JekyllSupport.new_attribute obj, :date, date
|
42
|
+
JekyllSupport.new_attribute obj, :description, description
|
43
|
+
JekyllSupport.new_attribute obj, :draft, draft
|
44
|
+
JekyllSupport.new_attribute obj, :extname, '.html'
|
45
|
+
JekyllSupport.new_attribute obj, :last_modified, last_modified
|
46
|
+
JekyllSupport.new_attribute obj, :logger, PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
|
47
|
+
JekyllSupport.new_attribute obj, :title, title
|
48
|
+
JekyllSupport.new_attribute obj, :url, url
|
49
|
+
|
50
|
+
JekyllSupport::APage.new obj, nil
|
51
|
+
rescue StandardError => e
|
52
|
+
puts e.full_message
|
53
|
+
end
|
54
|
+
|
55
|
+
# Create Array of JekyllSupport::APage from objects
|
56
|
+
# @param objects [Array] An array of Jekyll::Document, Jekyll::Page or file names
|
57
|
+
# @param origin [String] Indicates type of objects being passed
|
58
|
+
def self.apages_from_objects(objects, origin)
|
59
|
+
pages = []
|
60
|
+
objects.each do |object|
|
61
|
+
unless object.respond_to?(:logger)
|
62
|
+
JekyllSupport.new_attribute(object,
|
63
|
+
:logger,
|
64
|
+
PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config))
|
65
|
+
end
|
66
|
+
page = APage.new(object, origin)
|
67
|
+
pages << page unless page.data['exclude_from_all'] || page.path == 'redirect.html'
|
68
|
+
end
|
69
|
+
pages
|
70
|
+
end
|
71
|
+
|
72
|
+
# Defines a new attribute called `prop_name` in object `obj` and sets it to `prop_value`
|
73
|
+
def self.new_attribute(obj, prop_name, prop_value)
|
74
|
+
obj.class.module_eval { attr_accessor prop_name }
|
75
|
+
obj.instance_variable_set :"@#{prop_name}", prop_value
|
76
|
+
end
|
77
|
+
|
78
|
+
FIXNUM_MAX = (2**((0.size * 8) - 2)) - 1 unless defined? FIXNUM_MAX
|
79
|
+
END_OF_DAYS = 1_000_000_000_000 unless defined? END_OF_DAYS # One trillion years in the future
|
80
|
+
# Time.new is -4712-01-01
|
81
|
+
|
2
82
|
class APage
|
3
|
-
attr_reader :content, :data, :date, :description, :destination, :draft,
|
4
|
-
:
|
83
|
+
attr_reader :categories, :collection_name, :content, :data, :date, :description, :destination, :draft,
|
84
|
+
:excerpt, :ext, :extname, :href, :label, :last_modified, :last_modified_field,
|
85
|
+
:layout, :logger, :name, :origin, :path, :relative_path, :tags, :title, :type, :url
|
5
86
|
|
87
|
+
# @param obj can be a `Jekyll::Document` or a Hash with properties
|
88
|
+
# @param origin values: 'collection', 'individual_page', and 'static_file'
|
89
|
+
# (See method JekyllSupport.apages_from_objects)
|
6
90
|
def initialize(obj, origin)
|
91
|
+
@logger = obj.logger
|
7
92
|
@origin = origin
|
8
|
-
|
9
|
-
obj_field_init obj
|
10
|
-
@draft = Jekyll::Draft.draft? obj
|
11
|
-
@href = @url if @href.nil?
|
12
|
-
# @href = "/#{@href}" if @origin == 'individual_page'
|
13
|
-
@href = "#{@href}index.html" if @href.end_with? '/'
|
14
|
-
@name = File.basename(@href)
|
15
|
-
@title = if @data&.key?('title')
|
16
|
-
@data['title']
|
17
|
-
elsif obj.respond_to?(:title)
|
18
|
-
obj.title
|
19
|
-
else
|
20
|
-
"<code>#{@href}</code>"
|
21
|
-
end
|
93
|
+
build obj
|
22
94
|
rescue StandardError => e
|
23
|
-
JekyllSupport.error_short_trace(@logger, e)
|
24
|
-
|
95
|
+
::JekyllSupport.error_short_trace(@logger, e)
|
96
|
+
end
|
97
|
+
|
98
|
+
# @param name can be either a String or a Symbol
|
99
|
+
def field(name, use_default: true)
|
100
|
+
default_value = case name
|
101
|
+
when :date, :last_modified, :last_modified_at
|
102
|
+
END_OF_DAYS
|
103
|
+
else
|
104
|
+
''
|
105
|
+
end
|
106
|
+
|
107
|
+
result = data[name.to_sym] || data[name.to_s] if data.key?(name.to_sym) || data.key?(name.to_s)
|
108
|
+
return result if result
|
109
|
+
|
110
|
+
default_value if use_default
|
111
|
+
end
|
112
|
+
|
113
|
+
# Look within @data (if the property exists), then self for the given key as a symbol or a string
|
114
|
+
# @param key must be a symbol
|
115
|
+
# @return value of data[key] if key exists as a string or a symbol, else nil
|
116
|
+
def obj_field(obj, key)
|
117
|
+
if obj.respond_to? :data
|
118
|
+
return obj.data[key] if obj.data.key? key
|
119
|
+
|
120
|
+
return obj.data[key.to_s] if obj.data.key? key.to_s
|
121
|
+
end
|
122
|
+
return obj.send(key) if obj.respond_to?(key)
|
123
|
+
|
124
|
+
return unless obj.respond_to?(:key?)
|
125
|
+
return obj[key] if obj.key?(key)
|
126
|
+
|
127
|
+
obj[key.to_s] if obj.key?(key.to_s)
|
128
|
+
end
|
129
|
+
|
130
|
+
def order
|
131
|
+
if data.key?('order') || data.key?(:order)
|
132
|
+
data['order'] || data[:order]
|
133
|
+
else
|
134
|
+
FIXNUM_MAX
|
135
|
+
end
|
25
136
|
end
|
26
137
|
|
27
138
|
def to_s
|
@@ -30,40 +141,63 @@ module AllCollectionsHooks
|
|
30
141
|
|
31
142
|
private
|
32
143
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
@
|
41
|
-
@excerpt = @data['excerpt'] if @data.key? 'excerpt'
|
42
|
-
@ext ||= @data['ext'] if @data.key? 'ext'
|
43
|
-
@last_modified = @data['last_modified'] || @data['last_modified_at'] || @date
|
44
|
-
@last_modified_field = case @data
|
45
|
-
when @data.key?('last_modified')
|
46
|
-
'last_modified'
|
47
|
-
when @data.key?('last_modified_at')
|
48
|
-
'last_modified_at'
|
49
|
-
end
|
50
|
-
@layout = @data['layout'] if @data.key? 'layout'
|
51
|
-
@tags = @data['tags'] if @data.key? 'tags'
|
52
|
-
end
|
144
|
+
# Sets the following uninitialized instance attributes in APage from selected key/value pairs in `obj.data`:
|
145
|
+
# `categories`, `date`, `description`, `excerpt`, `ext`, `last_modified` or `last_modified_at`,
|
146
|
+
# `layout`, and `tags`.
|
147
|
+
# Sets the following instance attributes in APage from selected attributes in `obj` (when present):
|
148
|
+
# `content`, `destination`, `ext` and `extname`, `label` from `collection.label`,
|
149
|
+
# `path`, `relative_path`, `type`, and `url`.
|
150
|
+
def build(obj) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
151
|
+
@categories ||= obj_field(obj, :categories)
|
53
152
|
|
54
|
-
|
55
|
-
@
|
153
|
+
collection_value = obj_field(obj, :collection)
|
154
|
+
@collection_name = if collection_value
|
155
|
+
if collection_value.respond_to?(:label)
|
156
|
+
collection_value.label
|
157
|
+
elsif collection_value.key? :label
|
158
|
+
collection_value[:label]
|
159
|
+
end
|
160
|
+
end
|
56
161
|
|
162
|
+
@content ||= obj.content if obj.respond_to? :content
|
163
|
+
@data ||= obj.respond_to?(:data) ? obj.data : {}
|
164
|
+
@date ||= obj_field(obj, :date) || Time.now # Jekyll doc.date property is a Time
|
165
|
+
@description ||= obj_field(obj, :description)
|
57
166
|
# TODO: What _config.yml setting should be passed to destination()?
|
58
|
-
@destination
|
59
|
-
@
|
60
|
-
@
|
61
|
-
@
|
62
|
-
@
|
63
|
-
@
|
64
|
-
|
65
|
-
@
|
66
|
-
|
167
|
+
@destination ||= obj.destination('') if obj.respond_to? :destination
|
168
|
+
@draft ||= Jekyll::Draft.draft? obj
|
169
|
+
@excerpt ||= obj_field(obj, :excerpt)
|
170
|
+
@ext ||= obj_field(obj, :ext) || obj_field(obj, :extname)
|
171
|
+
@extname ||= @ext # For compatibility with previous versions of all_collections
|
172
|
+
@label ||= obj.collection.label if obj.respond_to?(:collection) && obj.collection.respond_to?(:label)
|
173
|
+
|
174
|
+
@last_modified ||= obj_field(obj, :last_modified) ||
|
175
|
+
obj_field(obj, :last_modified_at) ||
|
176
|
+
Date.parse(@date.to_s) # Jekyll doc.last_modified property is a Date
|
177
|
+
|
178
|
+
@last_modified_field ||= if obj_field(obj, :last_modified)
|
179
|
+
:last_modified
|
180
|
+
elsif obj_field(obj, :last_modified_at)
|
181
|
+
:last_modified_at
|
182
|
+
end
|
183
|
+
|
184
|
+
@layout ||= obj_field(obj, :layout)
|
185
|
+
@path ||= obj_field(obj, :path)
|
186
|
+
@relative_path ||= obj_field(obj, :relative_path)
|
187
|
+
@tags ||= obj_field(obj, :tags)
|
188
|
+
@type ||= obj_field(obj, :type)
|
189
|
+
|
190
|
+
@url ||= obj.url
|
191
|
+
if @url
|
192
|
+
@url = "#{@url}index.html" if @url&.end_with? '/'
|
193
|
+
else
|
194
|
+
@url = '/index.html'
|
195
|
+
end
|
196
|
+
|
197
|
+
# @href = "/#{@href}" if @origin == 'individual_page'
|
198
|
+
@href ||= @url
|
199
|
+
@name ||= File.basename(@href)
|
200
|
+
@title ||= obj_field(obj, :title) || "<code>#{@href}</code>"
|
67
201
|
end
|
68
202
|
end
|
69
203
|
end
|
@@ -22,8 +22,8 @@ module JekyllAllCollections
|
|
22
22
|
::AllCollectionsHooks.compute(site) if !@site.class.method_defined?(:all_documents) || @site.all_documents.nil?
|
23
23
|
end
|
24
24
|
rescue StandardError => e
|
25
|
-
JekyllSupport.error_short_trace(@logger, e)
|
26
|
-
# JekyllSupport.warn_short_trace(@logger, e)
|
25
|
+
::JekyllSupport.error_short_trace(@logger, e)
|
26
|
+
# ::JekyllSupport.warn_short_trace(@logger, e)
|
27
27
|
end
|
28
28
|
|
29
29
|
# Yes, all_collections is defined for this hook
|
@@ -31,8 +31,8 @@ module JekyllAllCollections
|
|
31
31
|
# defined_msg = ::AllCollectionsHooks.all_collections_defined?(site)
|
32
32
|
# @logger.debug { "Jekyll::Hooks.register(:site, :post_read, :low: #{defined_msg}" }
|
33
33
|
# rescue StandardError => e
|
34
|
-
# JekyllSupport.error_short_trace(@logger, e)
|
35
|
-
# # JekyllSupport.warn_short_trace(@logger, e)
|
34
|
+
# ::JekyllSupport.error_short_trace(@logger, e)
|
35
|
+
# # ::JekyllSupport.warn_short_trace(@logger, e)
|
36
36
|
# end
|
37
37
|
|
38
38
|
# Yes, all_collections is defined for this hook
|
@@ -40,8 +40,8 @@ module JekyllAllCollections
|
|
40
40
|
# defined_msg = ::AllCollectionsHooks.all_collections_defined?(site)
|
41
41
|
# @logger.debug { "Jekyll::Hooks.register(:site, :post_read, :normal: #{defined_msg}" }
|
42
42
|
# rescue StandardError => e
|
43
|
-
# JekyllSupport.error_short_trace(@logger, e)
|
44
|
-
# # JekyllSupport.warn_short_trace(@logger, e)
|
43
|
+
# ::JekyllSupport.error_short_trace(@logger, e)
|
44
|
+
# # ::JekyllSupport.warn_short_trace(@logger, e)
|
45
45
|
# end
|
46
46
|
|
47
47
|
# Yes, all_collections is defined for this hook
|
@@ -49,8 +49,8 @@ module JekyllAllCollections
|
|
49
49
|
# defined_msg = ::AllCollectionsHooks.all_collections_defined?(site)
|
50
50
|
# @logger.debug { "Jekyll::Hooks.register(:site, :pre_render: #{defined_msg}" }
|
51
51
|
# rescue StandardError => e
|
52
|
-
# JekyllSupport.error_short_trace(@logger, e)
|
53
|
-
# # JekyllSupport.warn_short_trace(@logger, e)
|
52
|
+
# ::JekyllSupport.error_short_trace(@logger, e)
|
53
|
+
# # ::JekyllSupport.warn_short_trace(@logger, e)
|
54
54
|
# end
|
55
55
|
end
|
56
56
|
end
|
data/lib/hooks/class_methods.rb
CHANGED
@@ -10,18 +10,6 @@ module AllCollectionsHooks
|
|
10
10
|
"site.all_collections #{site.class.method_defined?(:all_collections) ? 'IS' : 'IS NOT'} defined"
|
11
11
|
end
|
12
12
|
|
13
|
-
# Create Array of AllCollectionsHooks::APage from objects
|
14
|
-
# @param objects [Array] An array of Jekyll::Document, Jekyll::Page or file names
|
15
|
-
# @param origin [String] Indicates type of objects being passed
|
16
|
-
def self.apages_from_objects(objects, origin)
|
17
|
-
pages = []
|
18
|
-
objects.each do |object|
|
19
|
-
page = APage.new(object, origin)
|
20
|
-
pages << page unless page.data['exclude_from_all'] || page.path == 'redirect.html'
|
21
|
-
end
|
22
|
-
pages
|
23
|
-
end
|
24
|
-
|
25
13
|
# Called by early, high-priority hook.
|
26
14
|
# Computes site.all_collections, site.all_documents, site.everything, and site.sorted_lru_files
|
27
15
|
def self.compute(site)
|
@@ -32,11 +20,11 @@ module AllCollectionsHooks
|
|
32
20
|
.map { |x| x.class.method_defined?(:docs) ? x.docs : x }
|
33
21
|
.flatten
|
34
22
|
.compact
|
35
|
-
@all_collections =
|
23
|
+
@all_collections = JekyllSupport.apages_from_objects(documents, 'collection')
|
36
24
|
@all_documents = @all_collections +
|
37
|
-
|
25
|
+
JekyllSupport.apages_from_objects(site.pages, 'individual_page')
|
38
26
|
@everything = @all_documents +
|
39
|
-
|
27
|
+
JekyllSupport.apages_from_objects(site.static_files, 'static_file')
|
40
28
|
@sorted_lru_files = SortedLruFiles.new.add_pages @everything
|
41
29
|
|
42
30
|
site.all_collections = @all_collections
|
@@ -44,7 +32,7 @@ module AllCollectionsHooks
|
|
44
32
|
site.everything = @everything
|
45
33
|
site.sorted_lru_files = @sorted_lru_files
|
46
34
|
rescue StandardError => e
|
47
|
-
JekyllSupport.error_short_trace(::JekyllAllCollections::AllCollectionsHooks.logger, e)
|
48
|
-
# JekyllSupport.warn_short_trace(::JekyllAllCollections::AllCollectionsHooks.logger, e)
|
35
|
+
::JekyllSupport.error_short_trace(::JekyllAllCollections::AllCollectionsHooks.logger, e)
|
36
|
+
# ::JekyllSupport.warn_short_trace(::JekyllAllCollections::AllCollectionsHooks.logger, e)
|
49
37
|
end
|
50
38
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# require 'jekyll_draft'
|
2
1
|
require 'securerandom'
|
3
2
|
|
4
3
|
# @author Copyright 2020 Michael Slinn
|
@@ -15,17 +14,18 @@ module JekyllAllCollections
|
|
15
14
|
# @return [String]
|
16
15
|
def render_impl
|
17
16
|
parse_arguments # Defines instance variables like @sort_by
|
18
|
-
sort_lambda = init_sort_by @sort_by
|
19
|
-
@heading = @helper.parameter_specified?('heading') || default_head(@sort_by)
|
17
|
+
sort_lambda = init_sort_by @sort_by
|
20
18
|
generate_output sort_lambda
|
21
19
|
rescue StandardError => e
|
22
|
-
JekyllSupport.error_short_trace @logger, e
|
23
|
-
# JekyllSupport.warn_short_trace @logger, e
|
20
|
+
::JekyllSupport.error_short_trace @logger, e
|
21
|
+
# ::JekyllSupport.warn_short_trace @logger, e
|
24
22
|
end
|
25
23
|
|
26
|
-
# Descending sort keys reverse the order of comparison
|
27
|
-
#
|
28
|
-
#
|
24
|
+
# Descending sort keys are preceded by a minus sign, and reverse the order of comparison
|
25
|
+
# @param criteria String Examples: 'date', '-date', 'last_modified', '-last_modified',
|
26
|
+
# ['date', 'last_modified], ['-date', '-last_modified'], ['date', '-last_modified']
|
27
|
+
# @return values:
|
28
|
+
# "->(a, b) { [a.last_modified] <=> [b.last_modified] }" (ascending)
|
29
29
|
# "->(a, b) { [b.last_modified] <=> [a.last_modified] }" (descending)
|
30
30
|
# "->(a, b) { [a.last_modified, a.date] <=> [b.last_modified, b.date] }" (descending last_modified, ascending date)
|
31
31
|
# "->(a, b) { [a.last_modified, b.date] <=> [b.last_modified, a.date] }" (ascending last_modified, descending date)
|
@@ -76,43 +76,45 @@ module JekyllAllCollections
|
|
76
76
|
warn_short_trace e.red
|
77
77
|
end
|
78
78
|
|
79
|
-
def
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
79
|
+
def date_value(apage, field_name)
|
80
|
+
if %i[last_modified last_modified_at].include? field_name
|
81
|
+
apage.field(:last_modified_at, use_default: false) ||
|
82
|
+
apage.field(:last_modified, use_default: false) ||
|
83
|
+
Date.today
|
84
|
+
else
|
85
|
+
apage.date || Time.now
|
84
86
|
end
|
85
|
-
last_modified = if @date_column == 'last_modified' && apage.respond_to?(:last_modified)
|
86
|
-
apage.last_modified
|
87
|
-
elsif apage.respond_to? :last_modified_at
|
88
|
-
apage.last_modified_at
|
89
|
-
else
|
90
|
-
apage.date
|
91
|
-
end
|
92
|
-
last_modified ||= apage.date || Date.today
|
93
|
-
last_modified
|
94
87
|
end
|
95
88
|
|
96
89
|
def generate_output(sort_lambda)
|
97
|
-
id = @id.to_s.strip.empty? ? '' : " id
|
90
|
+
id = @id.to_s.strip.empty? ? '' : " id=\"#{@id}\""
|
98
91
|
heading = @heading.strip.to_s.empty? ? '' : "<h2#{id}>#{@heading}</h2>"
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
92
|
+
apages = case @data_selector
|
93
|
+
when 'all_collections'
|
94
|
+
@site.all_collections
|
95
|
+
when 'all_documents'
|
96
|
+
@site.all_documents
|
97
|
+
when 'everything'
|
98
|
+
@site.everything
|
99
|
+
else
|
100
|
+
raise AllCollectionsError, "Invalid value for @data_selector (#{data_selector})"
|
101
|
+
end
|
102
|
+
filtered_apages = @collection_name.nil? ? apages : apages.select { |apage| apage.collection_name == @collection_name }
|
103
|
+
sorted_apages = filtered_apages.sort(&sort_lambda)
|
104
|
+
posts = sorted_apages.map do |apage|
|
105
|
+
date_column = @date_column.to_s == 'last_modified' ? :last_modified : :date
|
106
|
+
d = date_value(apage, date_column)
|
107
|
+
if d.respond_to?(:strftime)
|
108
|
+
date = d.strftime '%Y-%m-%d'
|
109
|
+
else
|
110
|
+
@logger.error do
|
111
|
+
"date_value returned a #{d.class} instead of a class with a strftime method like Date and Time; date_column=#{date_column}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
draft = apage.draft ? DRAFT_HTML : ''
|
115
|
+
title = apage.title || apage.href
|
116
|
+
href = "<a href='#{apage.href}'>#{title}</a>"
|
117
|
+
@logger.debug { " date='#{date}' #{title}\n" }
|
116
118
|
" <span>#{date}</span><span>#{href}#{draft}</span>"
|
117
119
|
end
|
118
120
|
<<~END_TEXT
|
@@ -121,35 +123,50 @@ module JekyllAllCollections
|
|
121
123
|
#{posts.join "\n"}
|
122
124
|
</div>
|
123
125
|
END_TEXT
|
124
|
-
rescue ArgumentError => e
|
125
|
-
|
126
|
+
rescue NoMethodError || ArgumentError => e
|
127
|
+
::JekyllSupport.error_short_trace @logger, e
|
126
128
|
end
|
127
129
|
|
128
130
|
# See https://stackoverflow.com/a/75377832/553865
|
129
|
-
def init_sort_by(sort_by
|
131
|
+
def init_sort_by(sort_by)
|
130
132
|
sort_lambda_string = AllCollectionsTag.create_lambda_string sort_by
|
131
133
|
|
132
134
|
@logger.debug do
|
133
|
-
"#{@page['path']}
|
134
|
-
"sort_lambda_string = #{sort_lambda_string}\n"
|
135
|
+
"#{@page['path']} sort_lambda_string = #{sort_lambda_string}\n"
|
135
136
|
end
|
136
137
|
|
137
138
|
evaluate sort_lambda_string
|
138
139
|
end
|
139
140
|
|
141
|
+
# @return String defining the parsed sort_by expression
|
140
142
|
def parse_arguments
|
143
|
+
@collection_name = @helper.parameter_specified?('collection_name')
|
141
144
|
@data_selector = @helper.parameter_specified?('data_selector') || 'all_collections'
|
142
145
|
abort "Invalid data_selector #{@data_selector}" unless %w[all_collections all_documents everything].include? @data_selector
|
146
|
+
if (@data_selector != 'all_collections') && @collection_name
|
147
|
+
@logger.warn do
|
148
|
+
"collection_name was specified as '#{@collection_name}', but data_selector is #{@data_selector},
|
149
|
+
which is less effcient than specifying all_collections."
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
sort_by_param = @helper.parameter_specified? 'sort_by' # Might specify multiple sort fields
|
143
154
|
|
144
|
-
|
155
|
+
# Default to displaying last modified field unless a sort field is specified
|
156
|
+
@date_column = @helper.parameter_specified?('date_column') || 'last_modified'
|
145
157
|
unless %w[date last_modified].include?(@date_column)
|
146
158
|
raise AllCollectionsError "The date_column attribute must either have value 'date' or 'last_modified', " \
|
147
|
-
"but '#{@date_column}' was specified"
|
159
|
+
"but '#{@date_column}' was specified instead."
|
148
160
|
end
|
161
|
+
@date_column ||= (sort_by_param.include?('last_modified') ? 'last_modified' : 'date') # display the sort date by default
|
149
162
|
|
150
163
|
@id = @helper.parameter_specified?('id') || SecureRandom.hex(10)
|
151
|
-
|
152
|
-
@sort_by = (
|
164
|
+
|
165
|
+
@sort_by = (sort_by_param&.delete(' ')&.split(',') if sort_by_param != false) || ['-date']
|
166
|
+
|
167
|
+
@heading = @helper.parameter_specified?('heading') || default_head(@sort_by)
|
168
|
+
|
169
|
+
@sort_by
|
153
170
|
end
|
154
171
|
|
155
172
|
::JekyllSupport::JekyllPluginHelper.register(self, PLUGIN_NAME)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# Monkey patch StandardError so a new method called shorten_backtrace is added.
|
2
2
|
class StandardError
|
3
|
-
def shorten_backtrace(backtrace_element_count =
|
3
|
+
def shorten_backtrace(backtrace_element_count = 5)
|
4
|
+
set_backtrace backtrace[0..backtrace_element_count]
|
4
5
|
# self.backtrace = backtrace[0..backtrace_element_count].map do |x|
|
5
6
|
# raise JekyllPluginSupportError, "backtrace contains a #{x.class} with value '#{x}'." unless x.instance_of? String
|
6
7
|
|
@@ -14,7 +15,7 @@ module JekyllSupport
|
|
14
15
|
|
15
16
|
def self.error_short_trace(logger, error)
|
16
17
|
error.set_backtrace error.backtrace[0..DISPLAYED_CALLS]
|
17
|
-
logger.error { error }
|
18
|
+
logger.error { error.full_message } # Are error and logger.error defined?
|
18
19
|
error
|
19
20
|
end
|
20
21
|
|
@@ -28,6 +28,12 @@ module JekyllSupport
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
module ToString
|
32
|
+
def to_s
|
33
|
+
"#{self}.class.name"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
31
37
|
module NoArgParsing
|
32
38
|
attr_accessor :no_arg_parsing
|
33
39
|
|
@@ -37,17 +43,21 @@ end
|
|
37
43
|
module JekyllSupport
|
38
44
|
class JekyllTag
|
39
45
|
include JekyllSupportError
|
46
|
+
include ToString
|
40
47
|
end
|
41
48
|
|
42
49
|
class JekyllTagNoArgParsing
|
43
50
|
include JekyllSupportError
|
51
|
+
include ToString
|
44
52
|
end
|
45
53
|
|
46
54
|
class JekyllBlock
|
47
55
|
include JekyllSupportError
|
56
|
+
include ToString
|
48
57
|
end
|
49
58
|
|
50
59
|
class JekyllBlockNoArgParsing
|
51
60
|
include JekyllSupportError
|
61
|
+
include ToString
|
52
62
|
end
|
53
63
|
end
|
@@ -1,112 +1,184 @@
|
|
1
|
-
|
2
|
-
require_relative '../../lib/
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
require_relative '../../lib/hooks/a_page'
|
3
3
|
|
4
|
-
class
|
5
|
-
|
4
|
+
class NullBinding < BasicObject
|
5
|
+
include ::Kernel
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
# Avoid error message "warning: undefining `object_id' may cause serious problems"
|
8
|
+
# https://stackoverflow.com/a/17791631/553865
|
9
|
+
(
|
10
|
+
::Kernel.instance_methods(false) +
|
11
|
+
::Kernel.private_instance_methods(false) -
|
12
|
+
[:binding]
|
13
|
+
).each { |x| undef_method(x) unless x == :object_id }
|
12
14
|
|
13
|
-
def
|
14
|
-
|
15
|
+
def min_binding
|
16
|
+
binding
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
20
|
+
def show_dates(label, array)
|
21
|
+
puts " #{label} actual: #{array.map(&:title).join(', ')} <==> expected: #{expected.map(&:title).join(', ')}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def show(label, lambda_string, actual, expected)
|
25
|
+
puts "#{label} - For lambda_string: #{lambda_string}"
|
26
|
+
puts " actual: #{actual.map(&:title).join(', ')}"
|
27
|
+
puts "expected: #{expected.map(&:title).join(', ')}"
|
28
|
+
actual_array = actual.map do |x|
|
29
|
+
[
|
30
|
+
(x.date.strftime '%Y-%m-%d' + '/' + x.title), (x.last_modified.strftime '%Y-%m-%d' + '/' + x.title)
|
31
|
+
].join('/')
|
32
|
+
end
|
33
|
+
expected_array = expected.map do |x|
|
34
|
+
[
|
35
|
+
(x.date.strftime '%Y-%m-%d' + '/' + x.title), (x.last_modified.strftime '%Y-%m-%d' + '/' + x.title)
|
36
|
+
].join('/')
|
37
|
+
end
|
38
|
+
puts ' actual date/last_modified: ' + actual_array.join(', ')
|
39
|
+
puts 'expected date/last_modified: ' + expected_array.join(', ')
|
21
40
|
end
|
22
41
|
|
42
|
+
logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
|
43
|
+
|
23
44
|
# See https://stackoverflow.com/a/75388137/553865
|
24
|
-
RSpec.describe(
|
25
|
-
let(:o1)
|
26
|
-
|
27
|
-
|
28
|
-
|
45
|
+
RSpec.describe(JekyllSupport) do
|
46
|
+
let(:o1) do
|
47
|
+
described_class.apage_from(
|
48
|
+
collection_name: '_posts',
|
49
|
+
date: '2020-01-20',
|
50
|
+
last_modified: '2020-01-20',
|
51
|
+
logger: logger,
|
52
|
+
title: 'a_A (o1)'
|
53
|
+
)
|
54
|
+
end
|
55
|
+
let(:o2) do
|
56
|
+
described_class.apage_from(
|
57
|
+
collection_name: '_posts',
|
58
|
+
date: '2021-01-21',
|
59
|
+
last_modified: '2021-01-21',
|
60
|
+
logger: logger,
|
61
|
+
title: 'b_B (o2)'
|
62
|
+
)
|
63
|
+
end
|
64
|
+
let(:o3) do
|
65
|
+
described_class.apage_from(
|
66
|
+
collection_name: '_posts',
|
67
|
+
date: '2021-01-21',
|
68
|
+
last_modified: '2022-01-22',
|
69
|
+
logger: logger,
|
70
|
+
title: 'b_C (o3)'
|
71
|
+
)
|
72
|
+
end
|
73
|
+
let(:o4) do
|
74
|
+
described_class.apage_from(
|
75
|
+
collection_name: '_posts',
|
76
|
+
date: '2022-01-22',
|
77
|
+
last_modified: '2022-01-22',
|
78
|
+
logger: logger,
|
79
|
+
title: 'c_C (o4)'
|
80
|
+
)
|
81
|
+
end
|
29
82
|
let(:objs) { [o1, o2, o3, o4] }
|
30
83
|
|
31
|
-
it 'defines sort_by lambda with last_modified' do
|
84
|
+
it '(1) defines sort_by lambda with last_modified (ascending)' do
|
32
85
|
sort_lambda = ->(a, b) { [a.last_modified] <=> [b.last_modified] }
|
33
|
-
|
34
|
-
|
86
|
+
actual = objs.sort(&sort_lambda)
|
87
|
+
expected = [o1, o2, o3, o4]
|
88
|
+
show('(1)', '[a.last_modified] <=> [b.last_modified]', actual, expected)
|
89
|
+
expect(actual).to eq(expected)
|
35
90
|
end
|
36
91
|
|
37
|
-
it 'makes sort_by lambdas from stringified
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
92
|
+
it '(2) makes sort_by lambdas from stringified comparison of last_modified (ascending)' do
|
93
|
+
sort_lambda_string = '->(a, b) { a.last_modified <=> b.last_modified }'
|
94
|
+
sort_lambda = eval sort_lambda_string, NullBinding.new.min_binding, __FILE__, __LINE__ - 1
|
95
|
+
actual = objs.sort(&sort_lambda)
|
96
|
+
expected = [o1, o2, o3, o4]
|
97
|
+
show('(2)', sort_lambda_string, actual, expected)
|
98
|
+
expect(actual).to eq(expected)
|
42
99
|
end
|
43
100
|
|
44
|
-
it 'makes sort_by
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
101
|
+
it '(3) makes sort_by lambda from stringified array of last_modified (ascending)' do
|
102
|
+
sort_lambda_string = '->(a, b) { [a.last_modified] <=> [b.last_modified] }'
|
103
|
+
sort_lambda = eval sort_lambda_string, NullBinding.new.min_binding, __FILE__, __LINE__ - 1
|
104
|
+
actual = objs.sort(&sort_lambda)
|
105
|
+
expected = [o1, o2, o3, o4]
|
106
|
+
show('(3)', sort_lambda_string, actual, expected)
|
107
|
+
expect(actual).to eq(expected)
|
49
108
|
end
|
50
109
|
|
51
|
-
it 'makes sort_by
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
expected = [o3,
|
56
|
-
|
110
|
+
it '(4) makes sort_by lambda with last_modified (descending) from stringified array' do
|
111
|
+
sort_lambda_string = '->(a, b) { [b.last_modified] <=> [a.last_modified] }'
|
112
|
+
sort_lambda = eval sort_lambda_string, NullBinding.new.min_binding, __FILE__, __LINE__ - 1
|
113
|
+
actual = objs.sort(&sort_lambda)
|
114
|
+
expected = [o4, o3, o2, o1]
|
115
|
+
show('(4)', sort_lambda_string, actual, expected)
|
116
|
+
expect([o3, o4]).to include(actual[0]) # The sort might yield o3 or o4 in this position
|
117
|
+
expect([o3, o4]).to include(actual[1]) # The sort might yield o3 or o4 in this position
|
118
|
+
expect(o2).to eq(actual[2])
|
119
|
+
expect(o1).to eq(actual[3])
|
57
120
|
end
|
58
121
|
|
59
|
-
it 'create_lambda with
|
60
|
-
lambda_string =
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
122
|
+
it '(5) create_lambda with date (descending)' do
|
123
|
+
lambda_string = JekyllAllCollections::AllCollectionsTag.create_lambda_string('-last_modified')
|
124
|
+
expect(lambda_string).to eq('->(a, b) { [b.last_modified] <=> [a.last_modified] }')
|
125
|
+
sort_lambda = self.eval lambda_string, binding
|
126
|
+
actual = objs.sort(&sort_lambda)
|
127
|
+
expected = [o4, o3, o2, o1]
|
128
|
+
show('(5)', lambda_string, actual, expected)
|
129
|
+
expect([o3, o4]).to include(actual[0]) # The sort might yield o3 or o4 in this position
|
130
|
+
expect([o3, o4]).to include(actual[1]) # The sort might yield o3 or o4 in this position
|
131
|
+
expect(o2).to eq(actual[2])
|
132
|
+
expect(o1).to eq(actual[3])
|
66
133
|
end
|
67
134
|
|
68
|
-
it 'create_lambda with
|
69
|
-
lambda_string =
|
70
|
-
|
71
|
-
|
135
|
+
it '(6) create_lambda with date (ascending)' do
|
136
|
+
lambda_string = JekyllAllCollections::AllCollectionsTag.create_lambda_string('date')
|
137
|
+
expect(lambda_string).to eq('->(a, b) { [a.date] <=> [b.date] }')
|
138
|
+
sort_lambda = self.eval lambda_string, binding
|
139
|
+
actual = objs.sort(&sort_lambda)
|
72
140
|
expected = [o1, o2, o3, o4]
|
73
|
-
|
74
|
-
expect(
|
141
|
+
show('(1)', lambda_string, actual, expected)
|
142
|
+
expect(actual).to eq(expected)
|
75
143
|
end
|
76
144
|
|
77
|
-
it 'create_lambda with
|
78
|
-
lambda_string =
|
79
|
-
|
80
|
-
|
145
|
+
it '(7) create_lambda with date (ascending) and last_modified (ascending)' do
|
146
|
+
lambda_string = JekyllAllCollections::AllCollectionsTag.create_lambda_string(%w[date last_modified])
|
147
|
+
expect(lambda_string).to eq('->(a, b) { [a.date, a.last_modified] <=> [b.date, b.last_modified] }')
|
148
|
+
sort_lambda = self.eval lambda_string, binding
|
149
|
+
actual = objs.sort(&sort_lambda)
|
81
150
|
expected = [o1, o2, o3, o4]
|
82
|
-
|
83
|
-
expect(
|
151
|
+
show('(7)', lambda_string, actual, expected)
|
152
|
+
expect(actual).to eq(expected)
|
84
153
|
end
|
85
154
|
|
86
|
-
it 'create_lambda with
|
87
|
-
lambda_string =
|
88
|
-
|
89
|
-
|
155
|
+
it '(8) create_lambda with date (descending) and last_modified (descending)' do
|
156
|
+
lambda_string = JekyllAllCollections::AllCollectionsTag.create_lambda_string(['-date', '-last_modified'])
|
157
|
+
expect(lambda_string).to eq('->(a, b) { [b.date, b.last_modified] <=> [a.date, a.last_modified] }')
|
158
|
+
sort_lambda = self.eval lambda_string, binding
|
159
|
+
actual = objs.sort(&sort_lambda)
|
90
160
|
expected = [o4, o3, o2, o1]
|
91
|
-
|
92
|
-
expect(
|
161
|
+
show('(8)', lambda_string, actual, expected)
|
162
|
+
expect(actual).to eq(expected)
|
93
163
|
end
|
94
164
|
|
95
|
-
it 'create_lambda with
|
96
|
-
lambda_string =
|
97
|
-
|
98
|
-
|
165
|
+
it '(9) create_lambda with date (descending) and last_modified (ascending)' do
|
166
|
+
lambda_string = JekyllAllCollections::AllCollectionsTag.create_lambda_string(['-date', 'last_modified'])
|
167
|
+
expect(lambda_string).to eq('->(a, b) { [b.date, a.last_modified] <=> [a.date, b.last_modified] }')
|
168
|
+
sort_lambda = self.eval lambda_string, binding
|
169
|
+
actual = objs.sort(&sort_lambda)
|
99
170
|
expected = [o4, o2, o3, o1]
|
100
|
-
|
101
|
-
expect(
|
171
|
+
show('(9)', lambda_string, actual, expected)
|
172
|
+
expect(actual).to eq(expected)
|
102
173
|
end
|
103
174
|
|
104
|
-
it 'create_lambda with
|
105
|
-
lambda_string =
|
106
|
-
|
107
|
-
|
175
|
+
it '(10) create_lambda with date (ascending) and last_modified (descending)' do
|
176
|
+
lambda_string = JekyllAllCollections::AllCollectionsTag.create_lambda_string(['date', '-last_modified'])
|
177
|
+
expect(lambda_string).to eq('->(a, b) { [a.date, b.last_modified] <=> [b.date, a.last_modified] }')
|
178
|
+
sort_lambda = self.eval lambda_string, binding
|
179
|
+
actual = objs.sort(&sort_lambda)
|
108
180
|
expected = [o1, o3, o2, o4]
|
109
|
-
|
110
|
-
expect(
|
181
|
+
show('(10)', lambda_string, actual, expected)
|
182
|
+
expect(actual).to eq(expected)
|
111
183
|
end
|
112
184
|
end
|
data/spec/custom_error_spec.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
require 'spec_helper'
|
1
2
|
require_relative '../lib/error/jekyll_custom_error'
|
2
3
|
require_relative '../lib/jekyll_plugin_support/jekyll_plugin_support_class'
|
4
|
+
require_relative '../lib/helper/jekyll_plugin_helper'
|
3
5
|
|
4
6
|
class Dummy
|
5
7
|
def just_for_testing; end
|
@@ -14,14 +16,14 @@ class CustomErrorSpec
|
|
14
16
|
|
15
17
|
puts "AnError is a #{AnError.class}; StandardError is a #{StandardError.class}"
|
16
18
|
begin
|
17
|
-
raise AnError, '
|
19
|
+
raise AnError, 'This error is expected'
|
18
20
|
rescue AnError => e
|
19
21
|
puts "Caught AnError: #{e.message}"
|
20
22
|
rescue ::JekyllSupport::CustomError => e
|
21
23
|
puts "Caught CustomError: #{e.message}"
|
22
24
|
end
|
23
25
|
|
24
|
-
RSpec.describe JekyllSupport::JekyllPluginHelper do
|
26
|
+
RSpec.describe ::JekyllSupport::JekyllPluginHelper do
|
25
27
|
it 'generates messages' do
|
26
28
|
msg = described_class.generate_message(Dummy, tag_name, '0.1.0')
|
27
29
|
puts msg
|
data/spec/spec_helper.rb
CHANGED
@@ -4,9 +4,19 @@ require_relative '../lib/jekyll_plugin_support'
|
|
4
4
|
Jekyll.logger.log_level = :info
|
5
5
|
|
6
6
|
RSpec.configure do |config|
|
7
|
-
config.filter_run_when_matching focus: true
|
8
|
-
# config.order = 'random'
|
9
|
-
|
10
7
|
# See https://relishapp.com/rspec/rspec-core/docs/command-line/only-failures
|
11
8
|
config.example_status_persistence_file_path = 'spec/status_persistence.txt'
|
9
|
+
|
10
|
+
# See https://rspec.info/features/3-12/rspec-core/filtering/filter-run-when-matching/
|
11
|
+
# and https://github.com/rspec/rspec/issues/221
|
12
|
+
config.filter_run_when_matching :focus
|
13
|
+
|
14
|
+
# Other values: :progress, :html, :json, CustomFormatterClass
|
15
|
+
config.formatter = :documentation
|
16
|
+
|
17
|
+
# See https://rspec.info/features/3-12/rspec-core/command-line/order/
|
18
|
+
config.order = :defined
|
19
|
+
|
20
|
+
# See https://www.rubydoc.info/github/rspec/rspec-core/RSpec%2FCore%2FConfiguration:pending_failure_output
|
21
|
+
config.pending_failure_output = :skip
|
12
22
|
end
|
data/spec/status_persistence.txt
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
-
example_id
|
2
|
-
|
3
|
-
./spec/
|
1
|
+
example_id | status | run_time |
|
2
|
+
------------------------------------------------ | ------ | --------------- |
|
3
|
+
./spec/jekyll_plugin_helper_options_spec.rb[1:1] | passed | 0.00559 seconds |
|
4
|
+
./spec/jekyll_plugin_helper_options_spec.rb[1:2] | passed | 0.00583 seconds |
|
5
|
+
./spec/jekyll_plugin_helper_options_spec.rb[1:3] | passed | 0.00543 seconds |
|
6
|
+
./spec/jekyll_plugin_helper_options_spec.rb[1:4] | passed | 0.00157 seconds |
|
data/spec/testable_spec.rb
CHANGED
@@ -9,6 +9,15 @@ module TestModule
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
+
RSpec.describe(TestModule) do
|
13
|
+
extend described_class
|
14
|
+
|
15
|
+
it 'Invokes a_method from module' do
|
16
|
+
result = self.class.a_method
|
17
|
+
expect(result).to eq('a_method says Hi!')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
12
21
|
class TestClass
|
13
22
|
extend TestModule # Defines class methods
|
14
23
|
|
@@ -19,15 +28,6 @@ class TestClass
|
|
19
28
|
end
|
20
29
|
end
|
21
30
|
|
22
|
-
RSpec.describe(TestModule) do
|
23
|
-
extend described_class
|
24
|
-
|
25
|
-
it 'Invokes a_method from module' do
|
26
|
-
result = self.class.a_method
|
27
|
-
expect(result).to eq('a_method says Hi!')
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
31
|
RSpec.describe(TestClass) do
|
32
32
|
let(:o1) { described_class.new('value1', 'value2') }
|
33
33
|
|
metadata
CHANGED
@@ -1,15 +1,28 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll_plugin_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Slinn
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: bigdecimal
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - ">="
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '0'
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '0'
|
13
26
|
- !ruby/object:Gem::Dependency
|
14
27
|
name: facets
|
15
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,7 +107,6 @@ dependencies:
|
|
94
107
|
- - ">="
|
95
108
|
- !ruby/object:Gem::Version
|
96
109
|
version: '0'
|
97
|
-
description:
|
98
110
|
email:
|
99
111
|
- mslinn@mslinn.com
|
100
112
|
executables: []
|
@@ -169,8 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
169
181
|
- !ruby/object:Gem::Version
|
170
182
|
version: '0'
|
171
183
|
requirements: []
|
172
|
-
rubygems_version: 3.
|
173
|
-
signing_key:
|
184
|
+
rubygems_version: 3.6.9
|
174
185
|
specification_version: 4
|
175
186
|
summary: Provides a framework for writing and testing Jekyll plugins
|
176
187
|
test_files:
|