jekyll_plugin_support 1.1.0 → 3.0.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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +17 -1
  3. data/CHANGELOG.md +17 -6
  4. data/README.md +430 -2
  5. data/jekyll_plugin_support.gemspec +2 -1
  6. data/lib/block/jekyll_plugin_support_block.rb +2 -4
  7. data/lib/block/jekyll_plugin_support_block_noarg.rb +0 -2
  8. data/lib/generator/jekyll_plugin_support_generator.rb +1 -7
  9. data/lib/helper/jekyll_plugin_helper.rb +5 -5
  10. data/lib/helper/jekyll_plugin_helper_class.rb +2 -2
  11. data/lib/hooks/a_page.rb +69 -0
  12. data/lib/hooks/all_collections_hooks.rb +61 -0
  13. data/lib/hooks/all_files.rb +48 -0
  14. data/lib/hooks/class_methods.rb +50 -0
  15. data/lib/jekyll_all_collections/all_collections_tag.rb +157 -0
  16. data/lib/jekyll_plugin_support/jekyll_plugin_support_class.rb +3 -5
  17. data/lib/jekyll_plugin_support/jekyll_plugin_support_spec_support.rb +1 -3
  18. data/lib/jekyll_plugin_support/version.rb +1 -1
  19. data/lib/jekyll_plugin_support.rb +17 -12
  20. data/lib/tag/jekyll_plugin_support_tag.rb +1 -4
  21. data/lib/tag/jekyll_plugin_support_tag_noarg.rb +0 -2
  22. data/lib/util/mslinn_binary_search.rb +152 -0
  23. data/lib/util/send_chain.rb +56 -0
  24. data/spec/all_collections_tag/all_collections_tag_sort_spec.rb +112 -0
  25. data/spec/bsearch_spec.rb +50 -0
  26. data/spec/custom_error_spec.rb +9 -9
  27. data/spec/date_sort_spec.rb +84 -0
  28. data/spec/jekyll_plugin_helper_options_spec.rb +7 -3
  29. data/spec/liquid_variable_parsing_spec.rb +6 -6
  30. data/spec/mslinn_binary_search_spec.rb +47 -0
  31. data/spec/send_chain_spec.rb +72 -0
  32. data/spec/send_spec.rb +28 -0
  33. data/spec/sorted_lru_files_spec.rb +82 -0
  34. data/spec/spec_helper.rb +2 -0
  35. data/spec/status_persistence.txt +3 -9
  36. data/spec/testable_spec.rb +38 -0
  37. metadata +45 -5
@@ -0,0 +1,56 @@
1
+ # Supports one chain at a time
2
+ module SendChain
3
+ # See https://stackoverflow.com/a/79333706/553865
4
+ # This method can be called directly if no methods in the chain require arguments
5
+ # Does not use any external state
6
+ def send_chain(chain)
7
+ Array(chain).inject(self) { |o, a| o.send(*a) }
8
+ end
9
+
10
+ # Saves @chain structure containing :placeholders for arguments to be supplied later
11
+ # Call when a different chain with :placeholders is desired
12
+ def new_chain(chain)
13
+ abort "new_chain error: chain must be an array ('#{chain}' was an #{chain.class.name})" \
14
+ unless chain.instance_of?(Array)
15
+ @chain = chain
16
+ end
17
+
18
+ # Call after new_chain, to evaluate @chain with values
19
+ def substitute_and_send_chain_with(values)
20
+ send_chain substitute_chain_with values
21
+ end
22
+
23
+ alias evaluate_with substitute_and_send_chain_with
24
+
25
+ # Call this method after calling new_chain to perform error checking and replace :placeholders with values.
26
+ # @chain is not modified.
27
+ # @return [Array] Modified chain
28
+ def substitute_chain_with(values)
29
+ values = [values] unless values.instance_of?(Array)
30
+
31
+ placeholder_count = @chain.flatten.count { |x| x == :placeholder }
32
+ if values.length != placeholder_count
33
+ abort "with_values error: number of values (#{values.length}) does not match the number of placeholders (#{placeholder_count})"
34
+ end
35
+
36
+ eval_chain @chain, values
37
+ end
38
+
39
+ private
40
+
41
+ # Replaces :placeholders with values
42
+ # Does not use any external state
43
+ # @return modified chain
44
+ def eval_chain(chain, values)
45
+ chain.map do |c|
46
+ case c
47
+ when :placeholder
48
+ values.shift
49
+ when Array
50
+ eval_chain c, values
51
+ else
52
+ c
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+ require_relative '../../lib/jekyll_all_collections'
3
+
4
+ class APageStub
5
+ attr_reader :date, :last_modified, :label
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
12
+
13
+ def to_s
14
+ @label
15
+ end
16
+ end
17
+
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(', ')}"
21
+ end
22
+
23
+ # 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') }
29
+ let(:objs) { [o1, o2, o3, o4] }
30
+
31
+ it 'defines sort_by lambda with last_modified' do
32
+ 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])
35
+ end
36
+
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])
42
+ end
43
+
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])
49
+ end
50
+
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)
57
+ end
58
+
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)
66
+ end
67
+
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)
72
+ expected = [o1, o2, o3, o4]
73
+ # show(lambda_string, result, expected)
74
+ expect(result).to eq(expected)
75
+ end
76
+
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)
81
+ expected = [o1, o2, o3, o4]
82
+ # show(lambda_string, result, expected)
83
+ expect(result).to eq(expected)
84
+ end
85
+
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)
90
+ expected = [o4, o3, o2, o1]
91
+ # show(lambda_string, result, expected)
92
+ expect(result).to eq(expected)
93
+ end
94
+
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)
99
+ expected = [o4, o2, o3, o1]
100
+ # show(lambda_string, result, expected)
101
+ expect(result).to eq(expected)
102
+ end
103
+
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)
108
+ expected = [o1, o3, o2, o4]
109
+ # show(lambda_string, result, expected)
110
+ expect(result).to eq(expected)
111
+ end
112
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ # Ruby's binary search is unsuitable because ordering requirements are not stable.
4
+ # the value to be searched for changes the required ordering
5
+
6
+ RSpec.describe(Array) do
7
+ before { skip('Never gonna give you up/Never gonna let you down') }
8
+
9
+ sorted_ints = [0, 4, 7, 10, 12]
10
+ sorted_strings = %w[aaa aab aac bbb bbc bbd ccc ccd cce].sort.reverse
11
+
12
+ it 'returns index of first int match' do
13
+ actual = sorted_ints.bsearch_index { |x| x >= 4 }
14
+ expect(actual).to eq(1)
15
+
16
+ actual = sorted_ints.bsearch_index { |x| x >= 6 }
17
+ expect(actual).to eq(2)
18
+
19
+ actual = sorted_ints.bsearch_index { |x| x >= -1 }
20
+ expect(actual).to eq(0)
21
+
22
+ actual = sorted_ints.bsearch_index { |x| x >= 100 }
23
+ expect(actual).to be_nil
24
+ end
25
+
26
+ # See https://stackoverflow.com/q/79333097/553865
27
+ it 'returns index of first string match' do
28
+ puts(sorted_strings.map { |x| x.start_with? 'a' })
29
+ index = sorted_strings.bsearch_index { |x| x.start_with? 'a' }
30
+ expect(sorted_strings[index]).to eq('aac')
31
+
32
+ index = sorted_strings.bsearch_index { |x| x.start_with? 'aa' }
33
+ expect(sorted_strings[index]).to eq('aac')
34
+
35
+ index = sorted_strings.bsearch_index { |x| x.start_with? 'aaa' }
36
+ expect(sorted_strings[index]).to eq('aaa')
37
+
38
+ index = sorted_strings.bsearch_index { |x| x.start_with? 'b' }
39
+ expect(sorted_strings[index]).to eq('bbd')
40
+
41
+ index = sorted_strings.bsearch_index { |x| x.start_with? 'bb' }
42
+ expect(sorted_strings[index]).to eq('bbd')
43
+
44
+ index = sorted_strings.bsearch_index { |x| x.start_with? 'bbc' }
45
+ expect(sorted_strings[index]).to eq('bbc')
46
+
47
+ index = sorted_strings.bsearch_index { |x| x.start_with? 'cc' }
48
+ expect(sorted_strings[index]).to eq('cce')
49
+ end
50
+ end
@@ -1,5 +1,5 @@
1
- require_relative '../lib/jekyll_custom_error'
2
- require_relative '../lib/jekyll_plugin_support_class'
1
+ require_relative '../lib/error/jekyll_custom_error'
2
+ require_relative '../lib/jekyll_plugin_support/jekyll_plugin_support_class'
3
3
 
4
4
  class Dummy
5
5
  def just_for_testing; end
@@ -8,7 +8,7 @@ end
8
8
  class CustomErrorSpec
9
9
  tag_name = 'test_tag'
10
10
  argument_string = 'This is the argument string'
11
- AnError = JekyllSupport.define_error
11
+ AnError = ::JekyllSupport.define_error
12
12
  AnError.class_variable_set(:@@tag_name, tag_name)
13
13
  AnError.class_variable_set(:@@argument_string, argument_string)
14
14
 
@@ -17,21 +17,21 @@ class CustomErrorSpec
17
17
  raise AnError, 'Oops'
18
18
  rescue AnError => e
19
19
  puts "Caught AnError: #{e.message}"
20
- rescue JekyllSupport::CustomError => e
20
+ rescue ::JekyllSupport::CustomError => e
21
21
  puts "Caught CustomError: #{e.message}"
22
22
  end
23
23
 
24
- RSpec.describe JekyllPluginHelper do
24
+ RSpec.describe JekyllSupport::JekyllPluginHelper do
25
25
  it 'generates messages' do
26
26
  msg = described_class.generate_message(Dummy, tag_name, '0.1.0')
27
27
  puts msg
28
- expect(msg).to include(match(/Error class. DummyError/))
29
- expect(msg).to include(match(/CSS class for error messages. dummy_error/))
30
- expect(msg).to include(match(/die_on_dummy_error. false/))
28
+ expect(msg).to include('Error class: DummyError')
29
+ expect(msg).to include('CSS class for error messages: dummy_error')
30
+ expect(msg).to include('die_on_dummy_error: false')
31
31
  end
32
32
  end
33
33
 
34
- RSpec.describe JekyllSupport::CustomError do
34
+ RSpec.describe ::JekyllSupport::CustomError do
35
35
  it 'can create custom errors' do
36
36
  expect { raise AnError, 'Oops' }.to raise_error(AnError)
37
37
  end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/jekyll_plugin_support'
3
+
4
+ # Verifies how data comparisons work
5
+
6
+ class Obj
7
+ # `last_modified` is primary sort key
8
+ # `date` (when specified) is secondary sort key
9
+ attr_reader :date, :last_modified
10
+
11
+ def initialize(param1, param2)
12
+ @last_modified = Date.parse(param1)
13
+ @date = Date.parse(param2)
14
+ end
15
+ end
16
+
17
+ RSpec.describe(Obj) do
18
+ let(:o1) { described_class.new('2000-01-01', '2001-01-01') }
19
+ let(:o2) { described_class.new('2010-01-01', '2001-01-01') }
20
+ let(:o3) { described_class.new('2010-01-01', '2011-01-01') }
21
+ let(:o4) { described_class.new('2020-01-01', '2011-01-01') }
22
+ let(:objs) { [o1, o2, o3, o4] }
23
+
24
+ # See https://ruby-doc.org/3.2.0/Comparable.html
25
+ it 'compares one key with ascending dates' do
26
+ expect([o1.last_modified] <=> [o2.last_modified]).to eq(-1)
27
+ expect([o2.last_modified] <=> [o3.last_modified]).to eq(0)
28
+ expect([o3.last_modified] <=> [o4.last_modified]).to eq(-1)
29
+ end
30
+
31
+ it 'compares two keys with ascending dates' do
32
+ expect([o1.last_modified, o1.date] <=> [o2.last_modified, o2.date]).to eq(-1)
33
+ expect([o2.last_modified, o2.date] <=> [o3.last_modified, o3.date]).to eq(-1)
34
+ expect([o3.last_modified, o3.date] <=> [o4.last_modified, o4.date]).to eq(-1)
35
+ end
36
+
37
+ it 'compares one key with descending dates' do
38
+ expect([o1.last_modified] <=> [o2.last_modified]).to eq(-1)
39
+ expect([o2.last_modified] <=> [o3.last_modified]).to eq(0)
40
+ end
41
+
42
+ it 'compares two keys with descending dates' do
43
+ expect([o2.last_modified, o2.date] <=> [o1.last_modified, o1.date]).to eq(1)
44
+ expect([o3.last_modified, o3.date] <=> [o2.last_modified, o2.date]).to eq(1)
45
+ expect([o4.last_modified, o4.date] <=> [o3.last_modified, o3.date]).to eq(1)
46
+ end
47
+
48
+ # See https://ruby-doc.org/3.2.0/Enumerable.html#method-i-sort
49
+ it 'sort with one key ascending' do
50
+ sort_lambda = ->(a, b) { [a.last_modified] <=> [b.last_modified] }
51
+ result = objs.sort(&sort_lambda)
52
+ expect(result).to eq([o1, o2, o3, o4])
53
+ end
54
+
55
+ it 'sort with one key descending' do
56
+ sort_lambda = ->(a, b) { [b.last_modified] <=> [a.last_modified] }
57
+ result = objs.sort(&sort_lambda)
58
+ expect(result).to eq([o4, o2, o3, o1])
59
+ end
60
+
61
+ it 'sort with two keys ascending' do
62
+ sort_lambda = ->(a, b) { [a.last_modified, a.date] <=> [b.last_modified, b.date] }
63
+ result = objs.sort(&sort_lambda)
64
+ expect(result).to eq([o1, o2, o3, o4])
65
+ end
66
+
67
+ it 'sort with both keys descending' do
68
+ sort_lambda = ->(a, b) { [b.last_modified, b.date] <=> [a.last_modified, a.date] }
69
+ result = objs.sort(&sort_lambda)
70
+ expect(result).to eq([o4, o3, o2, o1])
71
+ end
72
+
73
+ it 'sort with last_modified descending and date ascending' do
74
+ sort_lambda = ->(a, b) { [b.last_modified, a.date] <=> [a.last_modified, b.date] }
75
+ result = objs.sort(&sort_lambda)
76
+ expect(result).to eq([o4, o2, o3, o1])
77
+ end
78
+
79
+ it 'sort with last_modified ascending and date descending' do
80
+ sort_lambda = ->(a, b) { [a.last_modified, b.date] <=> [b.last_modified, a.date] }
81
+ result = objs.sort(&sort_lambda)
82
+ expect(result).to eq([o1, o3, o2, o4])
83
+ end
84
+ end
@@ -1,14 +1,15 @@
1
1
  require 'jekyll_plugin_logger'
2
- require 'rspec/match_ignoring_whitespace'
2
+ # require 'rspec/match_ignoring_whitespace'
3
3
  require_relative '../lib/jekyll_plugin_support'
4
- require_relative '../lib/jekyll_plugin_support_spec_support'
4
+ require_relative '../lib/jekyll_plugin_support/jekyll_plugin_support_spec_support'
5
5
 
6
6
  class JekyllPluginHelperOptionsTest
7
- RSpec.describe JekyllPluginHelper do
7
+ RSpec.describe ::JekyllSupport::JekyllPluginHelper do
8
8
  logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
9
9
 
10
10
  it 'parses quoted string options' do
11
11
  helper = described_class.new('my_tag', "colors='blue or green' blah ick", logger, false)
12
+ helper.reinitialize helper.markup
12
13
  expect(helper.keys_values.keys).to eq(%w[colors blah ick])
13
14
 
14
15
  colors = helper.parameter_specified? 'colors'
@@ -19,6 +20,7 @@ class JekyllPluginHelperOptionsTest
19
20
 
20
21
  it 'parses unquoted string options' do
21
22
  helper = described_class.new('my_tag', 'color=blue blah ick', logger, false)
23
+ helper.reinitialize helper.markup
22
24
  expect(helper.keys_values.keys).to eq(%w[color blah ick])
23
25
 
24
26
  color = helper.parameter_specified? 'color'
@@ -29,6 +31,7 @@ class JekyllPluginHelperOptionsTest
29
31
 
30
32
  it 'parses quoted booleans' do
31
33
  helper = described_class.new('my_tag', "bool1='true' bool2='false' blah ick", logger, false)
34
+ helper.reinitialize helper.markup
32
35
  expect(helper.keys_values.keys).to eq(%w[bool1 bool2 blah ick])
33
36
 
34
37
  bool1 = helper.parameter_specified? 'bool1'
@@ -44,6 +47,7 @@ class JekyllPluginHelperOptionsTest
44
47
 
45
48
  it 'parses unquoted booleans' do
46
49
  helper = described_class.new('my_tag', 'bool1=true bool2=false blah ick', logger, false)
50
+ helper.reinitialize helper.markup
47
51
  expect(helper.keys_values.keys).to eq(%w[bool1 bool2 blah ick])
48
52
 
49
53
  bool1 = helper.parameter_specified? 'bool1'
@@ -1,11 +1,11 @@
1
1
  require 'jekyll_plugin_logger'
2
- require 'rspec/match_ignoring_whitespace'
2
+ # require 'rspec/match_ignoring_whitespace'
3
3
  require_relative '../lib/jekyll_plugin_support'
4
- require_relative '../lib/jekyll_plugin_support_spec_support'
4
+ require_relative '../lib/jekyll_plugin_support/jekyll_plugin_support_spec_support'
5
5
 
6
6
  class LiquidVariableParsing
7
7
  # @return copy of str with references to defined variables replaced by the values of the variables
8
- def variable_replace(str, scopes)
8
+ def self.variable_replace(str, scopes)
9
9
  result = str.clone
10
10
  match_data_list = str.to_enum(:scan, /{{[a-z_][a-zA-Z_0-9]*}}/).map { Regexp.last_match }.reverse
11
11
  match_data_list&.each do |md|
@@ -22,13 +22,13 @@ class LiquidVariableParsing
22
22
  result
23
23
  end
24
24
 
25
- RSpec.describe JekyllPluginHelper do
25
+ RSpec.describe ::JekyllSupport::JekyllPluginHelper do
26
26
  it 'substitutes variable references for values without recursion' do
27
27
  scopes = [{ 'a' => '{{', 'b' => 'asdf', 'c' => '}}' }]
28
28
  str = '{{a}}{{b}}{{c}} This should be unchanged: {{d}}'
29
- new_str = variable_replace(str, scopes)
29
+ new_str = LiquidVariableParsing.variable_replace(str, scopes)
30
30
  expect(str).to start_with('{{a}}')
31
- expect(new_str).to be('{{asdf}} This should be unchanged: {{d}}')
31
+ expect(new_str).to eq('{{asdf}} This should be unchanged: {{d}}')
32
32
  end
33
33
  end
34
34
  end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/hooks/all_files'
3
+
4
+ def build_msbs(sorted_strings)
5
+ sorted_strings.each do |string|
6
+ $msbs.insert LruFile.new(string.reverse, "Page #{string}") # { |x| x.url.start_with? string }
7
+ end
8
+ $msbs.enable_search
9
+ end
10
+
11
+ RSpec.describe(MSlinnBinarySearch) do
12
+ $msbs = described_class.new [:url, %i[start_with? placeholder]]
13
+ build_msbs %w[aaa.html baa.html caa.html bbb.html cbb.html dbb.html ccc.html ccd.html cce.html]
14
+
15
+ it 'handles an empty search string by returning the index of the first item (0)' do
16
+ index = $msbs.find_index '' # { |x| x.url.start_with? '' }
17
+ expect(index).to be_zero
18
+ end
19
+
20
+ it 'returns the index of the first partial match' do
21
+ index = $msbs.find_index 'a.html' # { |x| x.url.start_with? 'a.html' }
22
+ expect(index).to eq(0)
23
+
24
+ index = $msbs.find_index 'baa.html' # { |x| x.url.start_with? 'baa.html' }
25
+ expect(index).to eq(1)
26
+
27
+ index = $msbs.find_index 'c.html' # { |x| x.url.start_with? 'c.html' }
28
+ expect(index).to eq(6)
29
+
30
+ index = $msbs.find_index 'cce.html' # { |x| x.url.start_with? 'cce.html' }
31
+ expect(index).to eq(8)
32
+ end
33
+
34
+ it 'returns the item of the first match' do
35
+ item = $msbs.find 'a.html' # { |x| x.url.start_with? 'a.html' }
36
+ expect(item.url.reverse).to eq('aaa.html')
37
+
38
+ item = $msbs.find 'baa.html' # { |x| x.url.start_with? 'baa.html' }
39
+ expect(item.url.reverse).to eq('baa.html')
40
+
41
+ item = $msbs.find 'c.html' # { |x| x.url.start_with? 'c.html' }
42
+ expect(item.url.reverse).to eq('ccc.html')
43
+
44
+ item = $msbs.find 'cce.html' # { |x| x.url.start_with? 'cce.html' }
45
+ expect(item.url.reverse).to eq('cce.html')
46
+ end
47
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/util/send_chain'
3
+
4
+ unless defined? LruFile
5
+ LruFile = Struct.new(:url, :page) do
6
+ include SendChain
7
+ end
8
+ end
9
+
10
+ RSpec.describe(LruFile) do
11
+ lru_file = described_class.new 'abc', 'def'
12
+
13
+ it 'can perform a simple call if no arguments are required' do
14
+ # Equivalent to: lru_file.url.reverse
15
+ actual = lru_file.send_chain %i[url reverse]
16
+ expect(actual).to eq('cba')
17
+ end
18
+
19
+ it 'can accept a scalar argument in stages' do
20
+ lru_file.new_chain [:url, %i[end_with? placeholder]]
21
+ # Equivalent to: lru_file.url.end_with?('bc')
22
+ substituted_chain = lru_file.substitute_chain_with 'bc'
23
+ actual = lru_file.send_chain substituted_chain
24
+ expect(actual).to be true
25
+ end
26
+
27
+ it 'can accept a vector argument in stages' do
28
+ lru_file.new_chain [:url, %i[end_with? placeholder]]
29
+ # Next 2 lines are equivalent to: lru_file.url.end_with?('bc')
30
+ substituted_chain = lru_file.substitute_chain_with ['bc']
31
+ actual = lru_file.send_chain substituted_chain
32
+ expect(actual).to be true
33
+ end
34
+
35
+ it 'can accept a scalar argument in one stage' do
36
+ lru_file.new_chain [:url, %i[end_with? placeholder]]
37
+ # Equivalent to: lru_file.url.end_with?('bc')
38
+ actual = lru_file.substitute_and_send_chain_with 'bc'
39
+ expect(actual).to be true
40
+ end
41
+
42
+ it 'can accept an array argument in one stage' do
43
+ lru_file.new_chain [:url, %i[end_with? placeholder]]
44
+ # Equivalent to: lru_file.url.end_with?('bc')
45
+ actual = lru_file.substitute_and_send_chain_with ['bc']
46
+ expect(actual).to be true
47
+ end
48
+
49
+ it 'can use the evaluate_with alias' do
50
+ lru_file.new_chain [:url, %i[end_with? placeholder]]
51
+ # Equivalent to: lru_file.url.end_with?('bc')
52
+ actual = lru_file.evaluate_with ['bc']
53
+ expect(actual).to be true
54
+ end
55
+
56
+ it 'can reuse the chain with different values' do
57
+ lru_file.new_chain [:url, %i[end_with? placeholder]]
58
+
59
+ # Equivalent to: lru_file.url.end_with?('bc')
60
+ actual = lru_file.substitute_and_send_chain_with 'bc'
61
+ expect(actual).to be true
62
+
63
+ # Equivalent to: lru_file.url.end_with?('abc')
64
+ substituted_chain = lru_file.substitute_chain_with ['abc']
65
+ actual = lru_file.send_chain substituted_chain
66
+ expect(actual).to be true
67
+
68
+ # Equivalent to: lru_file.url.end_with?('de')
69
+ actual = lru_file.substitute_and_send_chain_with 'de'
70
+ expect(actual).to be false
71
+ end
72
+ end
data/spec/send_spec.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ # Exploring how to set date attributes in an object
4
+
5
+ class Obj
6
+ # `last_modified` is primary sort key
7
+ # `date` (when specified) is secondary sort key
8
+ attr_reader :date, :last_modified
9
+
10
+ def initialize(param1, param2)
11
+ @last_modified = Date.parse(param1)
12
+ @date = Date.parse(param2)
13
+ end
14
+ end
15
+
16
+ RSpec.describe(Obj) do
17
+ let(:obj) { described_class.new('2000-01-01', '2001-01-01') }
18
+
19
+ it 'can send date' do
20
+ date = obj.send :date
21
+ expect(obj.date).to eq(date)
22
+ end
23
+
24
+ it 'can send last_modified' do
25
+ last_modified = obj.send :last_modified
26
+ expect(obj.last_modified).to eq(last_modified)
27
+ end
28
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/hooks/all_files'
3
+
4
+ RSpec.describe(SortedLruFiles) do
5
+ expected1 = 'first-page.html'
6
+ expected2 = 'second-page.html'
7
+ expected3 = 'third-page.html'
8
+
9
+ it 'can read back an inserted item' do
10
+ sorted_files = described_class.new
11
+ sorted_files.insert(expected1, "https://mslinn.com/#{expected1}") # insert reverses expected1
12
+ sorted_files.enable_search
13
+
14
+ actual = sorted_files.select expected1
15
+ expect(actual.length).to eq(1)
16
+ expect(actual.first&.reverse&.start_with?(expected1.reverse)).to be true
17
+
18
+ actual = sorted_files.select expected1[5..]
19
+ expect(actual.length).to eq(1)
20
+ expect(actual.first&.reverse&.start_with?(expected1[5..].reverse)).to be true
21
+
22
+ actual = sorted_files.select 'should_not_match'
23
+ expect(actual).to be_empty
24
+ end
25
+
26
+ it 'works with 2 items and one match' do
27
+ sorted_files = described_class.new
28
+ sorted_files.insert(expected1, "https://mslinn.com/#{expected1}") # insert reverses expected1
29
+ sorted_files.insert(expected2, "https://mslinn.com/#{expected2}")
30
+ sorted_files.enable_search
31
+
32
+ expect(sorted_files.msbs.array[0].url).to be <= sorted_files.msbs.array[1].url
33
+
34
+ actual = sorted_files.select expected1
35
+ expect(actual.length).to eq(1)
36
+ expect(actual.first&.end_with?(expected1)).to be true
37
+
38
+ actual = sorted_files.select expected2
39
+ expect(actual.length).to eq(1)
40
+ expect(actual.first&.end_with?(expected2)).to be true
41
+ end
42
+
43
+ it 'handles multiple matches' do
44
+ sorted_files = described_class.new
45
+ sorted_files.insert(expected1, "https://mslinn.com/#{expected1}") # insert reverses expected1
46
+ sorted_files.insert(expected2, "https://mslinn.com/#{expected2}")
47
+ sorted_files.enable_search
48
+
49
+ expected = '.html'
50
+ actual = sorted_files.select expected
51
+ expect(actual.length).to eq(2)
52
+ expect(actual.first&.end_with?(expected)).to be true
53
+ end
54
+
55
+ it 'works with 3 items' do
56
+ sorted_files = described_class.new
57
+ sorted_files.insert(expected1, "https://mslinn.com/#{expected1}") # insert reverses expected1
58
+ sorted_files.insert(expected2, "https://mslinn.com/#{expected2}")
59
+ sorted_files.insert(expected3, "https://mslinn.com/#{expected3}")
60
+ sorted_files.enable_search
61
+
62
+ expect(sorted_files.msbs.array[0].url).to be <= sorted_files.msbs.array[1].url
63
+ expect(sorted_files.msbs.array[1].url).to be <= sorted_files.msbs.array[2].url
64
+
65
+ actual = sorted_files.select expected1
66
+ expect(actual.length).to eq(1)
67
+ expect(actual.first&.end_with?(expected1)).to be true
68
+
69
+ actual = sorted_files.select expected2
70
+ expect(actual.length).to eq(1)
71
+ expect(actual.first&.end_with?(expected2)).to be true
72
+
73
+ actual = sorted_files.select expected3
74
+ expect(actual.length).to eq(1)
75
+ expect(actual.first&.end_with?(expected3)).to be true
76
+
77
+ expected = '.html'
78
+ actual = sorted_files.select expected
79
+ expect(actual.length).to eq(3)
80
+ expect(actual.first&.end_with?(expected)).to be true
81
+ end
82
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'jekyll'
2
2
  require_relative '../lib/jekyll_plugin_support'
3
3
 
4
+ Jekyll.logger.log_level = :info
5
+
4
6
  RSpec.configure do |config|
5
7
  config.filter_run_when_matching focus: true
6
8
  # config.order = 'random'
@@ -1,9 +1,3 @@
1
- example_id | status | run_time |
2
- ------------------------------------------------ | ------ | --------------- |
3
- ./spec/custom_error_spec.rb[1:1] | failed | 0.00772 seconds |
4
- ./spec/custom_error_spec.rb[2:1] | passed | 0.0011 seconds |
5
- ./spec/jekyll_plugin_helper_options_spec.rb[1:1] | failed | 0.00005 seconds |
6
- ./spec/jekyll_plugin_helper_options_spec.rb[1:2] | failed | 0.00003 seconds |
7
- ./spec/jekyll_plugin_helper_options_spec.rb[1:3] | failed | 0.00003 seconds |
8
- ./spec/jekyll_plugin_helper_options_spec.rb[1:4] | failed | 0.00003 seconds |
9
- ./spec/liquid_variable_parsing_spec.rb[1:1] | failed | 0.00003 seconds |
1
+ example_id | status | run_time |
2
+ ----------------------------------------------- | ------ | --------------- |
3
+ ./spec/jekyll_block_plugin_support_spec.rb[1:1] | passed | 0.00062 seconds |