jekyll_plugin_support 0.7.2 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,94 @@
1
+ require_relative 'jekyll_plugin_error_handling'
2
+
3
+ module JekyllSupport
4
+ # Base class for Jekyll block tags
5
+ class JekyllBlock < Liquid::Block
6
+ attr_reader :argument_string, :helper, :line_number, :logger, :page, :site, :text
7
+
8
+ include JekyllSupportErrorHandling
9
+ extend JekyllSupportErrorHandling
10
+
11
+ def set_error_context
12
+ error_class = Object.const_get error_class_name
13
+ error_class.class_variable_set(:@@argument_string, @argument_string)
14
+ error_class.class_variable_set(:@@line_number, @line_number)
15
+ error_class.class_variable_set(:@@path, @page['path'])
16
+ error_class.class_variable_set(:@@tag_name, @tag_name)
17
+ end
18
+
19
+ # See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
20
+ # @param tag_name [String] the name of the tag, which we usually know.
21
+ # @param argument_string [String] the arguments passed to the tag, as a single string.
22
+ # @param parse_context [Liquid::ParseContext] hash that stores Liquid options.
23
+ # By default it has two keys: :locale and :line_numbers, the first is a Liquid::I18n object, and the second,
24
+ # a boolean parameter that determines if error messages should display the line number the error occurred.
25
+ # This argument is used mostly to display localized error messages on Liquid built-in Tags and Filters.
26
+ # See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
27
+ # @return [void]
28
+ def initialize(tag_name, markup, parse_context)
29
+ super
30
+ @tag_name = tag_name
31
+ @argument_string = markup.to_s # Vars in plugin parameters cannot be replaced yet
32
+ @logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
33
+ @logger.debug { "#{self.class}: respond_to?(:no_arg_parsing) #{respond_to?(:no_arg_parsing) ? 'yes' : 'no'}." }
34
+ @helper = JekyllPluginHelper.new tag_name, markup, @logger, respond_to?(:no_arg_parsing)
35
+
36
+ @error_name = "#{tag_name.camelcase(:upper)}Error"
37
+ Jekyll::CustomError.factory @error_name
38
+ end
39
+
40
+ # Method prescribed by the Jekyll plugin lifecycle.
41
+ # Defines @config, @envs, @mode, @page and @site
42
+ # @return [String]
43
+ def render(liquid_context)
44
+ @helper.liquid_context = JekyllSupport.inject_vars @logger, liquid_context
45
+ text = super # Liquid variable values in content are looked up and substituted
46
+
47
+ @envs = liquid_context.environments.first
48
+ @page = liquid_context.registers[:page] # hash
49
+ @scopes = liquid_context.scopes
50
+ @site = liquid_context.registers[:site]
51
+
52
+ @config = @site.config
53
+ @tag_config = @config[@tag_name]
54
+
55
+ set_error_context @error_name
56
+
57
+ @layout = @envs[:layout]
58
+ @paginator = @envs[:paginator]
59
+ @theme = @envs[:theme]
60
+
61
+ @mode = @config['env']&.key?('JEKYLL_ENV') ? @config['env']['JEKYLL_ENV'] : 'development'
62
+
63
+ @helper.reinitialize(@markup.strip)
64
+
65
+ @attribution = @helper.parameter_specified?('attribution') || false unless @no_arg_parsing
66
+ @logger.debug { "@keys_values='#{@keys_values}'" }
67
+
68
+ markup = JekyllSupport.lookup_liquid_variables liquid_context, @argument_string
69
+ @helper.reinitialize markup
70
+
71
+ render_impl text
72
+ rescue StandardError => e
73
+ e.shorten_backtrace
74
+ @logger.error { "#{e.class} on line #{@line_number} of #{e.backtrace[0].split(':').first} by #{tag_name} - #{e.message}" }
75
+ binding.pry if @pry_on_standard_error # rubocop:disable Lint/Debugger
76
+ raise e if @die_on_standard_error
77
+
78
+ <<~END_MSG
79
+ <div class='standard_error'>
80
+ #{e.class} on line #{@line_number} of #{e.backtrace[0].split(':').first} by #{tag_name}: #{e.message}
81
+ </div>
82
+ END_MSG
83
+ end
84
+
85
+ # Jekyll plugins should override this method, not render,
86
+ # so they can be tested more easily.
87
+ # The following variables are predefined:
88
+ # @argument_string, @config, @envs, @helper, @layout, @logger, @mode, @page, @paginator, @site, @tag_name and @theme
89
+ # @return [String] The result to be rendered to the invoking page
90
+ def render_impl(text)
91
+ text
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,30 @@
1
+ require_relative 'jekyll_plugin_error_handling'
2
+
3
+ module JekyllSupport
4
+ class JekyllBlockNoArgParsing < JekyllBlock
5
+ attr_reader :argument_string, :helper, :line_number, :logger, :page, :site
6
+
7
+ include JekyllSupportErrorHandling
8
+ extend JekyllSupportErrorHandling
9
+
10
+ def initialize(tag_name, argument_string, parse_context)
11
+ class << self
12
+ include NoArgParsing
13
+ end
14
+
15
+ super
16
+ @logger.debug { "#{self.class}: respond_to?(:o_arg_parsing) #{respond_to?(:no_arg_parsing) ? 'yes' : 'no'}." }
17
+ rescue StandardError => e
18
+ e.shorten_backtrace
19
+ @logger.error { e.full_message }
20
+ JekyllSupport.error_short_trace(@logger, e)
21
+ end
22
+
23
+ # Jekyll plugins must override this method, not render, so their plugin can be tested more easily
24
+ # The following variables are predefined:
25
+ # @argument_string, @config, @envs, @helper, @layout, @logger, @mode, @page, @paginator, @site, @tag_name and @theme
26
+ def render_impl
27
+ abort "#{self.class}.render_impl for tag #{@tag_name} must be overridden, but it was not."
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,88 @@
1
+ require_relative 'jekyll_custom_error'
2
+
3
+ # Monkey patch StandardError so a new method called shorten_backtrace is added.
4
+ class StandardError
5
+ def shorten_backtrace(backtrace_element_count = 3)
6
+ # self.backtrace = backtrace[0..backtrace_element_count].map do |x|
7
+ # raise JekyllPluginSupportError, "backtrace contains a #{x.class} with value '#{x}'." unless x.instance_of? String
8
+
9
+ # x.gsub(Dir.pwd + '/', './')
10
+ # end
11
+ end
12
+ end
13
+
14
+ module JekyllSupport
15
+ DISPLAYED_CALLS = 8
16
+
17
+ def self.error_short_trace(logger, error)
18
+ error.set_backtrace error.backtrace[0..DISPLAYED_CALLS]
19
+ logger.error { error }
20
+ error
21
+ end
22
+
23
+ # @return a new StandardError subclass containing the shorten_backtrace method
24
+ def define_error
25
+ Class.new Jekyll::CustomError
26
+ end
27
+ module_function :define_error
28
+
29
+ JekyllPluginSupportError = define_error
30
+
31
+ def self.dump_vars(_logger, liquid_context)
32
+ page = liquid_context.registers[:page]
33
+ vars = liquid_context.scopes.map do |scope|
34
+ scope.map { |name, value| " #{name} = #{value}" }.join("\n")
35
+ end.join("\n")
36
+ puts <<~END_MSG
37
+ #{page['name']} variables after injecting any defined in _config.yml:
38
+ #{vars}
39
+ END_MSG
40
+ end
41
+
42
+ # Add variable definitions from _config.yml to liquid_context
43
+ # Modifies liquid_context in the caller (call by reference)
44
+ # @return modified liquid_context
45
+ # See README.md#configuration-variable-definitions
46
+ # See demo/variables.html
47
+ def self.inject_vars(_logger, liquid_context)
48
+ site = liquid_context.registers[:site]
49
+
50
+ plugin_variables = site.config['liquid_vars']
51
+ return liquid_context unless plugin_variables
52
+
53
+ scope = liquid_context.scopes.last
54
+
55
+ env = site.config['env']
56
+ mode = env&.key?('JEKYLL_ENV') ? env['JEKYLL_ENV'] : 'development'
57
+
58
+ # Set default values
59
+ plugin_variables&.each do |name, value|
60
+ scope[name] = value if value.instance_of? String
61
+ end
62
+
63
+ # Override with environment-specific values
64
+ plugin_variables[mode]&.each do |name, value|
65
+ scope[name] = value if value.instance_of? String
66
+ end
67
+
68
+ liquid_context
69
+ end
70
+
71
+ def self.lookup_liquid_variables(liquid_context, markup)
72
+ liquid_context.scopes.each do |scope|
73
+ scope.each do |name, value|
74
+ markup = markup.gsub("{{#{name}}}", value.to_s)
75
+ end
76
+ end
77
+ markup
78
+ end
79
+
80
+ def self.warn_short_trace(logger, error)
81
+ remaining = error.backtrace.length - DISPLAYED_CALLS
82
+ logger.warn do
83
+ error.message + "\n" +
84
+ error.backtrace.take(DISPLAYED_CALLS).join("\n") +
85
+ "\n...Remaining #{remaining} call sites elided.\n"
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,91 @@
1
+ require 'pry'
2
+ require_relative 'jekyll_plugin_error_handling'
3
+
4
+ module JekyllSupport
5
+ # Base class for Jekyll tags
6
+ class JekyllTag < Liquid::Tag
7
+ attr_reader :argument_string, :helper, :line_number, :logger, :page, :site
8
+
9
+ include JekyllSupportErrorHandling
10
+ extend JekyllSupportErrorHandling
11
+
12
+ # See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
13
+ # @param tag_name [String] the name of the tag, which we usually know.
14
+ # @param argument_string [String] the arguments passed to the tag, as a single string.
15
+ # @param parse_context [Liquid::ParseContext] hash that stores Liquid options.
16
+ # By default it has two keys: :locale and :line_numbers, the first is a Liquid::I18n object, and the second,
17
+ # a boolean parameter that determines if error messages should display the line number the error occurred.
18
+ # This argument is used mostly to display localized error messages on Liquid built-in Tags and Filters.
19
+ # See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
20
+ # @return [void]
21
+ def initialize(tag_name, markup, parse_context)
22
+ super
23
+ @tag_name = tag_name
24
+ raise JekyllPluginSupportError, "markup is a #{markup.class} with value '#{markup}'." unless markup.instance_of? String
25
+
26
+ @argument_string = markup
27
+ @logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
28
+ @logger.debug { "#{self.class}: respond_to?(:no_arg_parsing) #{respond_to?(:no_arg_parsing) ? 'yes' : 'no'}." }
29
+ @helper = JekyllPluginHelper.new(tag_name, @argument_string, @logger, respond_to?(:no_arg_parsing))
30
+
31
+ @error_name = "#{tag_name.camelcase(:upper)}Error"
32
+ Jekyll::CustomError.factory @error_name
33
+ end
34
+
35
+ def set_error_context
36
+ error_class = Object.const_get @error_name
37
+ error_class.class_variable_set(:@@argument_string, @argument_string)
38
+ error_class.class_variable_set(:@@line_number, @line_number)
39
+ error_class.class_variable_set(:@@path, @page['path'])
40
+ error_class.class_variable_set(:@@tag_name, @tag_name)
41
+ end
42
+
43
+ # Method prescribed by the Jekyll plugin lifecycle.
44
+ def render(liquid_context)
45
+ return if @helper.excerpt_caller
46
+
47
+ @helper.liquid_context = JekyllSupport.inject_vars @logger, liquid_context
48
+
49
+ @envs = liquid_context.environments.first
50
+ @page = liquid_context.registers[:page]
51
+ @scopes = liquid_context.scopes
52
+ @site = liquid_context.registers[:site]
53
+
54
+ @config = @site.config
55
+ @tag_config = @config[@tag_name]
56
+ @jps = @config['jekyll_plugin_support']
57
+ @pry_on_standard_error = @jps['pry_on_standard_error'] || false if @jps
58
+
59
+ set_error_context @error_name
60
+
61
+ # @envs.keys are :content, :highlighter_prefix, :highlighter_suffix, :jekyll, :layout, :page, :paginator, :site, :theme
62
+ @layout = @envs[:layout]
63
+ @paginator = @envs[:paginator]
64
+ @theme = @envs[:theme]
65
+
66
+ @mode = @config['env']&.key?('JEKYLL_ENV') ? @config['env']['JEKYLL_ENV'] : 'development'
67
+
68
+ @helper.reinitialize JekyllSupport.lookup_liquid_variables liquid_context, @argument_string
69
+
70
+ render_impl
71
+ rescue StandardError => e
72
+ e.shorten_backtrace
73
+ @logger.error { "#{e.class} on line #{@line_number} of #{e.backtrace[0].split(':').first} while processing #{tag_name} - #{e.message}" }
74
+ binding.pry if @pry_on_standard_error # rubocop:disable Lint/Debugger
75
+ raise e if @die_on_standard_error
76
+
77
+ <<~END_MSG
78
+ <div class='standard_error'>
79
+ #{e.class} on line #{@line_number} of #{e.backtrace[0].split(':').first} while processing #{tag_name}: #{e.message}
80
+ </div>
81
+ END_MSG
82
+ end
83
+
84
+ # Jekyll plugins must override this method, not render, so their plugin can be tested more easily
85
+ # The following variables are predefined:
86
+ # @argument_string, @config, @envs, @helper, @layout, @logger, @mode, @page, @paginator, @site, @tag_name and @theme
87
+ def render_impl
88
+ abort "#{self.class}.render_impl for tag #{@tag_name} must be overridden, but it was not."
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'jekyll_plugin_error_handling'
2
+
3
+ module JekyllSupport
4
+ class JekyllTagNoArgParsing < JekyllTag
5
+ attr_reader :argument_string, :helper, :line_number, :logger, :page, :site
6
+
7
+ include JekyllSupportErrorHandling
8
+ extend JekyllSupportErrorHandling
9
+
10
+ def initialize(tag_name, argument_string, parse_context)
11
+ class << self
12
+ include NoArgParsing
13
+ end
14
+
15
+ super
16
+ @logger.debug { "#{self.class}: respond_to?(:no_arg_parsing) #{respond_to?(:no_arg_parsing) ? 'yes' : 'no'}." }
17
+ end
18
+
19
+ # Jekyll plugins must override this method, not render, so their plugin can be tested more easily
20
+ # The following variables are predefined:
21
+ # @argument_string, @config, @envs, @helper, @layout, @logger, @mode, @page, @paginator, @site, @tag_name and @theme
22
+ def render_impl
23
+ abort "#{self.class}.render_impl for tag #{@tag_name} must be overridden, but it was not."
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,39 @@
1
+ require_relative '../lib/jekyll_custom_error'
2
+ require_relative '../lib/jekyll_plugin_support_class'
3
+
4
+ class Dummy
5
+ def just_for_testing; end
6
+ end
7
+
8
+ class CustomErrorSpec
9
+ tag_name = 'test_tag'
10
+ argument_string = 'This is the argument string'
11
+ AnError = JekyllSupport.define_error
12
+ AnError.class_variable_set(:@@tag_name, tag_name)
13
+ AnError.class_variable_set(:@@argument_string, argument_string)
14
+
15
+ puts "AnError is a #{AnError.class}; StandardError is a #{StandardError.class}"
16
+ begin
17
+ raise AnError, 'Oops'
18
+ rescue AnError => e
19
+ puts "Caught AnError: #{e.message}"
20
+ rescue Jekyll::CustomError => e
21
+ puts "Caught CustomError: #{e.message}"
22
+ end
23
+
24
+ RSpec.describe JekyllPluginHelper do
25
+ it 'generates messages' do
26
+ msg = described_class.generate_message(Dummy, tag_name, '0.1.0')
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/))
31
+ end
32
+ end
33
+
34
+ RSpec.describe Jekyll::CustomError do
35
+ it 'can create custom errors' do
36
+ expect { raise AnError, 'Oops' }.to raise_error(AnError)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,34 @@
1
+ require 'jekyll_plugin_logger'
2
+ require 'rspec/match_ignoring_whitespace'
3
+ require_relative '../lib/jekyll_plugin_support'
4
+ require_relative '../lib/jekyll_plugin_support_spec_support'
5
+
6
+ class LiquidVariableParsing
7
+ # @return copy of str with references to defined variables replaced by the values of the variables
8
+ def variable_replace(str, scopes)
9
+ result = str.clone
10
+ match_data_list = str.to_enum(:scan, /{{[a-z_][a-zA-Z_0-9]*}}/).map { Regexp.last_match }.reverse
11
+ match_data_list.each do |md|
12
+ from = md.begin(0)
13
+ to = md.end(0) - 1
14
+ ref = str[from..to]
15
+ name = ref[2..-3]
16
+ scopes.each do |scope|
17
+ value = scope.key?(name) ? scope[name] : ref
18
+ # puts "str=#{str}; from=#{from}; to=#{to}; name=#{name} value=#{value}"
19
+ result[from..to] = value
20
+ end
21
+ end
22
+ result
23
+ end
24
+
25
+ RSpec.describe JekyllPluginHelper do
26
+ it 'substitutes variable references for values without recursion' do
27
+ scopes = [{ 'a' => '{{', 'b' => 'asdf', 'c' => '}}' }]
28
+ str = '{{a}}{{b}}{{c}} This should be unchanged: {{d}}'
29
+ new_str = variable_replace(str, scopes)
30
+ expect(str).to start_with('{{a}}')
31
+ expect(new_str).to be('{{asdf}} This should be unchanged: {{d}}')
32
+ end
33
+ end
34
+ end
data/spec/spec_helper.rb CHANGED
@@ -2,9 +2,8 @@ require 'jekyll'
2
2
  require_relative '../lib/jekyll_plugin_support'
3
3
 
4
4
  RSpec.configure do |config|
5
- config.filter_run :focus
5
+ config.filter_run_when_matching focus: true
6
6
  # config.order = 'random'
7
- config.run_all_when_everything_filtered = true
8
7
 
9
8
  # See https://relishapp.com/rspec/rspec-core/docs/command-line/only-failures
10
9
  config.example_status_persistence_file_path = 'spec/status_persistence.txt'
@@ -0,0 +1,6 @@
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 |
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll_plugin_support
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Slinn
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-08-14 00:00:00.000000000 Z
11
+ date: 2024-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: facets
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  description:
70
84
  email:
71
85
  - mslinn@mslinn.com
@@ -80,13 +94,22 @@ files:
80
94
  - README.md
81
95
  - Rakefile
82
96
  - jekyll_plugin_support.gemspec
83
- - lib/call_chain.rb
84
- - lib/gem_support.rb
97
+ - lib/jekyll_custom_error.rb
98
+ - lib/jekyll_plugin_error_handling.rb
85
99
  - lib/jekyll_plugin_helper.rb
100
+ - lib/jekyll_plugin_helper_attribution.rb
101
+ - lib/jekyll_plugin_helper_class.rb
86
102
  - lib/jekyll_plugin_support.rb
87
103
  - lib/jekyll_plugin_support/version.rb
104
+ - lib/jekyll_plugin_support_block.rb
105
+ - lib/jekyll_plugin_support_block_noarg.rb
106
+ - lib/jekyll_plugin_support_class.rb
88
107
  - lib/jekyll_plugin_support_spec_support.rb
108
+ - lib/jekyll_plugin_support_tag.rb
109
+ - lib/jekyll_plugin_support_tag_noarg.rb
110
+ - spec/custom_error_spec.rb
89
111
  - spec/jekyll_plugin_helper_options_spec.rb
112
+ - spec/liquid_variable_parsing_spec.rb
90
113
  - spec/spec_helper.rb
91
114
  - spec/status_persistence.txt
92
115
  homepage: https://www.mslinn.com/jekyll_plugins/jekyll_plugin_support.html
@@ -116,12 +139,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
139
  - !ruby/object:Gem::Version
117
140
  version: '0'
118
141
  requirements: []
119
- rubygems_version: 3.3.3
142
+ rubygems_version: 3.4.22
120
143
  signing_key:
121
144
  specification_version: 4
122
- summary: Provides support for writing Jekyll plugins.
145
+ summary: Provides a framework for writing and testing Jekyll plugins
123
146
  test_files:
147
+ - spec/custom_error_spec.rb
124
148
  - spec/jekyll_plugin_helper_options_spec.rb
149
+ - spec/liquid_variable_parsing_spec.rb
125
150
  - spec/spec_helper.rb
126
151
  - spec/status_persistence.txt
127
152
  ...
data/lib/call_chain.rb DELETED
@@ -1,54 +0,0 @@
1
- # TODO: File not used, delete
2
-
3
- # See https://stackoverflow.com/a/23363883/553865
4
- module CallChain
5
- ACaller = Struct.new(:filepath, :line, :method_name)
6
-
7
- def self.caller_method(depth = 1)
8
- parse_caller(caller(depth + 1).first).method_name
9
- end
10
-
11
- def self.parse_caller(at)
12
- return unless /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
13
-
14
- last_match = Regexp.last_match.to_a
15
- ACaller.new(
16
- last_match[1],
17
- last_match[2].to_i,
18
- last_match[3]
19
- )
20
- end
21
-
22
- def self.excerpt_caller
23
- call_sequence = caller
24
- call_sequence.each do |caller_|
25
- parsed_caller = parse_caller caller_
26
- filepath = parsed_caller.filepath
27
- excerpt = filepath.match? %r{jekyll[.0-9-]*/lib/jekyll/excerpt.rb\z}
28
- puts "excerpt matched #{filepath}" if excerpt
29
- return true if excerpt
30
- end
31
- false
32
- end
33
-
34
- # Return ACaller prior to jekyll_plugin_support
35
- def self.jpsh_subclass_caller
36
- state = :nothing_found
37
- call_sequence = caller
38
- call_sequence.each do |caller_|
39
- parsed_caller = parse_caller caller_
40
- filepath = parsed_caller.filepath
41
- dirname = File.dirname filepath
42
- jpsh = dirname.match? %r{jekyll_plugin_support[.0-9-]*/lib\z}
43
- liquid = dirname.match? %r{liquid[.0-9-]*/lib/\z}
44
- case state
45
- when :nothing_found
46
- state = :jpsh_found if jpsh
47
- when :jpsh_found
48
- # puts "Called from #{parsed_caller.filepath}, on line #{parsed_caller.line}, by method '#{parsed_caller.method_name}'" unless jpsh
49
- return parsed_caller unless jpsh || liquid
50
- end
51
- end
52
- nil
53
- end
54
- end
data/lib/gem_support.rb DELETED
@@ -1,19 +0,0 @@
1
- # See https://stackoverflow.com/a/75890279/553865
2
- module GemSupport
3
- # @param file must be a fully qualified file name that points to a file within a gem.
4
- # @return Gem::Specification of gem that file points into, or nil if not called from a gem
5
- def self.current_spec(file)
6
- abort 'GemSupport::current_spec: file is nil' if file.nil?
7
- return nil unless File.exist?(file)
8
-
9
- searcher = if Gem::Specification.respond_to?(:find)
10
- Gem::Specification
11
- elsif Gem.respond_to?(:searcher)
12
- Gem.searcher.init_gemspecs
13
- end
14
-
15
- searcher&.find do |spec|
16
- file.start_with? spec.full_gem_path
17
- end
18
- end
19
- end