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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 74f595dc019d923dbbad9e84b1eacdaa15808b36d54fc692044e30f26e0767f1
4
- data.tar.gz: 5632b03e8d9d29080ae0c43428d5c9a13243c4df529255013d63951d669a670d
3
+ metadata.gz: c20bec384d298ac931d132f59dbcaf621e9f55440954dc8c6579b1c9131df62e
4
+ data.tar.gz: 4cfd22137529da35c52f788ab70ec81fe9457d6b533ec5bc70f653b22791db0e
5
5
  SHA512:
6
- metadata.gz: b5839393146e5d1ab2317f004a563bad4144467e506fd41516f489b065fa52d00bfcea4eedc7d8d06028afd35cba34b3360b19f4d968ec6a456e429f6a2af542
7
- data.tar.gz: 203f6111c4127b4909534d4dcc6b7dcb7f3f5d7bbf9fa60016920558a6eb9faed7cd736212b8c3f25cb52514e21b75035dd00ea55928525127b9ca662ede224d
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: 25
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: 25
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', '>= 1.1.0'
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', '>= 1.1.0'
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='asdf'
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 `a href` values in website HTML.
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 { "#{e.class} on line #{@line_number} #{of_page} while processing #{tag_name} #{in_file_name}- #{e.message}" }
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 = 3)
46
- b = backtrace[0..backtrace_element_count - 1].map do |x|
47
- x.gsub(Dir.pwd + '/', './')
48
- end
49
- set_backtrace b
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
- module AllCollectionsHooks
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, :excerpt, :ext, :extname, :href,
4
- :label, :last_modified, :layout, :origin, :path, :relative_path, :tags, :title, :type, :url
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
- data_field_init obj
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
- # JekyllSupport.warn_short_trace(@logger, e)
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
- def data_field_init(obj)
34
- return unless obj.respond_to? :data
35
-
36
- @data = obj.data
37
-
38
- @categories = @data['categories'] if @data.key? 'categories'
39
- @date = (@data['date'].to_date if @data&.key?('date')) || Date.today
40
- @description = @data['description'] if @data.key? 'description'
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
- def obj_field_init(obj)
55
- @content = obj.content if obj.respond_to? :content
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 = obj.destination('') if obj.respond_to? :destination
59
- @ext = obj.extname
60
- @extname = @ext # For compatibility with previous versions of all_collections
61
- @label = obj.collection.label if obj.respond_to?(:collection) && obj.collection.respond_to?(:label)
62
- @path = obj.path if obj.respond_to? :path
63
- @relative_path = obj.relative_path if obj.respond_to? :relative_path
64
- @type = obj.type if obj.respond_to? :type
65
- @url = obj.url
66
- @url = "#{@url}index.html" if @url.end_with? '/'
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
@@ -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 = AllCollectionsHooks.apages_from_objects(documents, 'collection')
23
+ @all_collections = JekyllSupport.apages_from_objects(documents, 'collection')
36
24
  @all_documents = @all_collections +
37
- AllCollectionsHooks.apages_from_objects(site.pages, 'individual_page')
25
+ JekyllSupport.apages_from_objects(site.pages, 'individual_page')
38
26
  @everything = @all_documents +
39
- AllCollectionsHooks.apages_from_objects(site.static_files, 'static_file')
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, @sort_by_param
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
- # Example return values:
28
- # "->(a, b) { [a.last_modified] <=> [b.last_modified] }"
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 last_modified_value(apage)
80
- @logger.debug do
81
- " apage.last_modified='#{apage.last_modified}'; " \
82
- "apage.last_modified_at='#{apage.last_modified_at}'; " \
83
- "@date_column='#{@date_column}'"
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='#{@id}'"
90
+ id = @id.to_s.strip.empty? ? '' : " id=\"#{@id}\""
98
91
  heading = @heading.strip.to_s.empty? ? '' : "<h2#{id}>#{@heading}</h2>"
99
- data = case @data_selector
100
- when 'all_collections'
101
- @site.all_collections
102
- when 'all_documents'
103
- @site.all_documents
104
- when 'everything'
105
- @site.everything
106
- else
107
- raise AllCollectionsError, "Invalid value for @data_selector (#{data_selector})"
108
- end
109
- collection = data.sort(&sort_lambda)
110
- posts = collection.map do |x|
111
- last_modified = last_modified_value x
112
- date = last_modified.strftime '%Y-%m-%d'
113
- draft = x.draft ? DRAFT_HTML : ''
114
- href = "<a href='#{x.href}'>#{x.title}</a>"
115
- @logger.debug { " date='#{date}' #{x.title}\n" }
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
- warn_short_trace e
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, sort_by_param)
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']} sort_by_param=#{sort_by_param} " \
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
- @date_column = @helper.parameter_specified?('date_column') || 'date'
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
- @sort_by_param = @helper.parameter_specified? 'sort_by'
152
- @sort_by = (@sort_by_param&.delete(' ')&.split(',') if @sort_by_param != false) || ['-date']
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)
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
 
@@ -1,3 +1,3 @@
1
1
  module JekyllPluginSupportVersion
2
- VERSION = '3.0.0'.freeze unless defined?(VERSION)
2
+ VERSION = '3.1.0'.freeze unless defined?(VERSION)
3
3
  end
@@ -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
- require 'spec_helper'
2
- require_relative '../../lib/jekyll_all_collections'
1
+ require_relative '../spec_helper'
2
+ require_relative '../../lib/hooks/a_page'
3
3
 
4
- class APageStub
5
- attr_reader :date, :last_modified, :label
4
+ class NullBinding < BasicObject
5
+ include ::Kernel
6
6
 
7
- def initialize(date, last_modified, label = '')
8
- @date = Date.parse date
9
- @last_modified = Date.parse last_modified
10
- @label = label
11
- end
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 to_s
14
- @label
15
+ def min_binding
16
+ binding
15
17
  end
16
18
  end
17
19
 
18
- def show(lambda_string, result, expected)
19
- p "For lambda_string: #{lambda_string}"
20
- p " result: #{result.map(&:label).join(', ')} <==> expected: #{expected.map(&:label).join(', ')}"
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(AllCollectionsTag::AllCollectionsTag) do
25
- let(:o1) { APageStub.new('2020-01-01', '2020-01-01', 'a_A') }
26
- let(:o2) { APageStub.new('2021-01-01', '2020-01-01', 'b_A') }
27
- let(:o3) { APageStub.new('2021-01-01', '2023-01-01', 'b_B') }
28
- let(:o4) { APageStub.new('2022-01-01', '2023-01-01', 'c_B') }
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
- result = objs.sort(&sort_lambda)
34
- expect(result).to eq([o1, o2, o3, o4])
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 date' do
38
- sort_lambda = eval '->(a, b) { a.last_modified <=> b.last_modified }',
39
- NullBinding.new.min_binding, __FILE__, __LINE__ - 1
40
- result = objs.sort(&sort_lambda)
41
- expect(result).to eq([o1, o2, o3, o4])
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 lambdas from stringified array of last_modified' do
45
- sort_lambda = eval '->(a, b) { [a.last_modified] <=> [b.last_modified] }',
46
- NullBinding.new.min_binding, __FILE__, __LINE__ - 1
47
- result = objs.sort(&sort_lambda)
48
- expect(result).to eq([o1, o2, o3, o4])
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 lambdas with descending keys from stringified array of last_modified' do
52
- sort_lambda = eval '->(a, b) { [b.last_modified] <=> [a.last_modified] }',
53
- NullBinding.new.min_binding, __FILE__, __LINE__ - 1
54
- result = objs.sort(&sort_lambda)
55
- expected = [o3, o4, o1, o2]
56
- expect(result).to eq(expected)
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 1 date key, descending' do
60
- lambda_string = described_class.create_lambda_string('-last_modified')
61
- sort_lambda = described_class.evaluate(lambda_string)
62
- result = objs.sort(&sort_lambda)
63
- expected = [o3, o4, o1, o2]
64
- # show(lambda_string, result, expected)
65
- expect(result).to eq(expected)
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 1 date key, ascending' do
69
- lambda_string = described_class.create_lambda_string('date')
70
- sort_lambda = described_class.evaluate(lambda_string)
71
- result = objs.sort(&sort_lambda)
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
- # show(lambda_string, result, expected)
74
- expect(result).to eq(expected)
141
+ show('(1)', lambda_string, actual, expected)
142
+ expect(actual).to eq(expected)
75
143
  end
76
144
 
77
- it 'create_lambda with 2 date keys, both ascending' do
78
- lambda_string = described_class.create_lambda_string(%w[date last_modified])
79
- sort_lambda = described_class.evaluate(lambda_string)
80
- result = objs.sort(&sort_lambda)
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
- # show(lambda_string, result, expected)
83
- expect(result).to eq(expected)
151
+ show('(7)', lambda_string, actual, expected)
152
+ expect(actual).to eq(expected)
84
153
  end
85
154
 
86
- it 'create_lambda with 2 date keys, both descending' do
87
- lambda_string = described_class.create_lambda_string(['-date', '-last_modified'])
88
- sort_lambda = described_class.evaluate(lambda_string)
89
- result = objs.sort(&sort_lambda)
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
- # show(lambda_string, result, expected)
92
- expect(result).to eq(expected)
161
+ show('(8)', lambda_string, actual, expected)
162
+ expect(actual).to eq(expected)
93
163
  end
94
164
 
95
- it 'create_lambda with 2 date keys, first descending and second ascending' do
96
- lambda_string = described_class.create_lambda_string(['-date', 'last_modified'])
97
- sort_lambda = described_class.evaluate(lambda_string)
98
- result = objs.sort(&sort_lambda)
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
- # show(lambda_string, result, expected)
101
- expect(result).to eq(expected)
171
+ show('(9)', lambda_string, actual, expected)
172
+ expect(actual).to eq(expected)
102
173
  end
103
174
 
104
- it 'create_lambda with 2 date keys, first ascending and second descending' do
105
- lambda_string = described_class.create_lambda_string(['date', '-last_modified'])
106
- sort_lambda = described_class.evaluate(lambda_string)
107
- result = objs.sort(&sort_lambda)
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
- # show(lambda_string, result, expected)
110
- expect(result).to eq(expected)
181
+ show('(10)', lambda_string, actual, expected)
182
+ expect(actual).to eq(expected)
111
183
  end
112
184
  end
@@ -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, 'Oops'
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
@@ -1,4 +1,6 @@
1
+ require 'jekyll'
1
2
  require 'jekyll_plugin_logger'
3
+ require 'spec_helper'
2
4
  # require 'rspec/match_ignoring_whitespace'
3
5
  require_relative '../lib/jekyll_plugin_support'
4
6
  require_relative '../lib/jekyll_plugin_support/jekyll_plugin_support_spec_support'
@@ -1,4 +1,5 @@
1
1
  require 'jekyll_plugin_logger'
2
+ require 'spec_helper'
2
3
  # require 'rspec/match_ignoring_whitespace'
3
4
  require_relative '../lib/jekyll_plugin_support'
4
5
  require_relative '../lib/jekyll_plugin_support/jekyll_plugin_support_spec_support'
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
@@ -1,3 +1,6 @@
1
- example_id | status | run_time |
2
- ----------------------------------------------- | ------ | --------------- |
3
- ./spec/jekyll_block_plugin_support_spec.rb[1:1] | passed | 0.00062 seconds |
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 |
@@ -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.0.0
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: 2025-03-06 00:00:00.000000000 Z
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.5.22
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: