jekyll_plugin_support 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -1
- data/CHANGELOG.md +5 -0
- data/lib/jekyll_custom_error.rb +55 -0
- data/lib/jekyll_plugin_error_handling.rb +4 -1
- data/lib/jekyll_plugin_helper.rb +1 -1
- data/lib/jekyll_plugin_helper_class.rb +45 -5
- data/lib/jekyll_plugin_support/version.rb +1 -1
- data/lib/jekyll_plugin_support.rb +1 -0
- data/lib/jekyll_plugin_support_block.rb +20 -3
- data/lib/jekyll_plugin_support_class.rb +4 -2
- data/lib/jekyll_plugin_support_tag.rb +19 -3
- data/spec/custom_error_spec.rb +39 -0
- data/spec/status_persistence.txt +4 -5
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4efc790e49d3b2d98eb4e96bee8c75a18df25fcf7c08d66a44ef96d7c6db19c6
|
4
|
+
data.tar.gz: 6629e04d2170911427e4914c0d356e3f9c95149b7a673b2638242ba43cbe11fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5afd0123f178c5fe89ddbfbf55e48a63630a3ebdffe07b28b60e6ba5d0df0ee1c7f6c5b4dc25ca0c77c5e0fe4329a46cf9902585cadbcc9ea90fed032dc4b459
|
7
|
+
data.tar.gz: fd6cb95f84f50655b12e81a069a6cdf85ec265f244159b200909ec9d7c8559871c4a781ddf162b10dd9a53eefb07614ed7cec172877130a52e2859a306df0512
|
data/.rubocop.yml
CHANGED
@@ -30,7 +30,7 @@ Layout/LineLength:
|
|
30
30
|
Max: 150
|
31
31
|
|
32
32
|
Metrics/AbcSize:
|
33
|
-
Max:
|
33
|
+
Max: 55
|
34
34
|
|
35
35
|
Metrics/BlockLength:
|
36
36
|
Exclude:
|
@@ -64,6 +64,9 @@ RSpec/IndexedLet:
|
|
64
64
|
RSpec/MultipleExpectations:
|
65
65
|
Max: 15
|
66
66
|
|
67
|
+
Style/ClassVars:
|
68
|
+
Enabled: false
|
69
|
+
|
67
70
|
Style/Documentation:
|
68
71
|
Enabled: false
|
69
72
|
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'facets/string/camelcase'
|
2
|
+
require 'facets/string/snakecase'
|
3
|
+
|
4
|
+
module Jekyll
|
5
|
+
# Use like this:
|
6
|
+
# CustomError.new(:MyError, 'blah', 'asdf')
|
7
|
+
class CustomError < StandardError
|
8
|
+
def self.factory(name)
|
9
|
+
return if Object.const_defined? name
|
10
|
+
|
11
|
+
puts "Defining #{name}".yellow
|
12
|
+
eval "#{name} = Class.new Jekyll::CustomError" # rubocop:disable Style/EvalWithLocation, Security/Eval
|
13
|
+
end
|
14
|
+
|
15
|
+
def error_name
|
16
|
+
self.class.name.split('::').last
|
17
|
+
end
|
18
|
+
|
19
|
+
def calling_file
|
20
|
+
file_fq, _line_number, _extra = backtrace[0].split(':')
|
21
|
+
file_fq
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return HTML <div> tag with class set to the snake_case version of the error class name.
|
25
|
+
def html_message
|
26
|
+
shorten_backtrace
|
27
|
+
line_number = self.class.class_variable_get :@@line_number
|
28
|
+
path = self.class.class_variable_get :@@path
|
29
|
+
<<~END_MSG
|
30
|
+
<div class='#{error_name.snakecase}'>
|
31
|
+
#{self.class} raised in #{calling_file} while processing line #{line_number} (after front matter) of #{path}
|
32
|
+
#{message}
|
33
|
+
</div>
|
34
|
+
END_MSG
|
35
|
+
end
|
36
|
+
|
37
|
+
def logger_message
|
38
|
+
shorten_backtrace
|
39
|
+
kaller = caller(1..1).first
|
40
|
+
line_number = self.class.class_variable_get :@@line_number
|
41
|
+
path = self.class.class_variable_get :@@path
|
42
|
+
<<~END_MSG
|
43
|
+
#{error_name} raised in #{kaller} while processing line #{line_number} (after front matter) of #{path}
|
44
|
+
#{message}
|
45
|
+
END_MSG
|
46
|
+
end
|
47
|
+
|
48
|
+
def shorten_backtrace(backtrace_element_count = 3)
|
49
|
+
b = backtrace[0..backtrace_element_count - 1].map do |x|
|
50
|
+
x.gsub(Dir.pwd + '/', './')
|
51
|
+
end
|
52
|
+
set_backtrace b
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -19,20 +19,23 @@ module JekyllSupportErrorHandling
|
|
19
19
|
rescue StandardError => e
|
20
20
|
file, line_number, caller = e.backtrace[caller_index].split(':')
|
21
21
|
caller = caller.tr('`', "'")
|
22
|
-
warn "#{error.
|
22
|
+
warn "#{error.message} #{caller} on line #{line_number} (after front matter) of #{file}".red
|
23
23
|
# Process.kill('HUP', Process.pid) # generates huge stack trace
|
24
24
|
exec "echo ''"
|
25
25
|
end
|
26
26
|
|
27
|
+
# TODO: Delete this
|
27
28
|
def format_error_message(message)
|
28
29
|
page = " of #{@page['path']}" if @page
|
29
30
|
remove_ansi_color "on line #{line_number} (after front matter)#{page}.\n#{message}"
|
30
31
|
end
|
31
32
|
|
33
|
+
# TODO: Delete this
|
32
34
|
def remove_ansi_color(string)
|
33
35
|
string.gsub(/\e\[([;\d]+)?m/, '')
|
34
36
|
end
|
35
37
|
|
38
|
+
# TODO: Delete this
|
36
39
|
def maybe_reraise_error(error, throw_error: true)
|
37
40
|
fmsg = format_error_message "#{error.class}: #{error.message.strip}"
|
38
41
|
@logger.error { fmsg }
|
data/lib/jekyll_plugin_helper.rb
CHANGED
@@ -25,7 +25,7 @@ class JekyllPluginHelper
|
|
25
25
|
@markup = markup
|
26
26
|
rescue StandardError => e
|
27
27
|
e.shorten_backtrace
|
28
|
-
@logger.error { e.
|
28
|
+
@logger.error { e.message }
|
29
29
|
end
|
30
30
|
|
31
31
|
# @return undefined if parameter was specified, removes it from the available tokens and returns value
|
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'facets/string/camelcase'
|
2
|
+
require 'facets/string/snakecase'
|
3
|
+
require 'yaml'
|
4
|
+
|
1
5
|
# Class methods for JekyllPluginHelper
|
2
6
|
class JekyllPluginHelper
|
3
7
|
# Expand an environment variable reference
|
@@ -11,19 +15,55 @@ class JekyllPluginHelper
|
|
11
15
|
end
|
12
16
|
end
|
13
17
|
|
14
|
-
def self.
|
15
|
-
|
18
|
+
def self.generate_message(klass, tag_name, version)
|
19
|
+
error_ruby_class_name = "#{klass.name.camelcase(:upper)}Error"
|
20
|
+
config_die_key = "die_on_#{error_ruby_class_name.snakecase}"
|
21
|
+
error_css_class_name = error_ruby_class_name.split('::').last.snakecase
|
22
|
+
# config_file_fq = File.realpath 'demo/_config.yml'
|
23
|
+
config = YAML.load_file('demo/_config.yml')
|
24
|
+
tag_config = config[tag_name]
|
25
|
+
tag_config_msg = if tag_config.nil?
|
26
|
+
<<~END_MSG
|
27
|
+
_config.yml does not contain configuration information for this plugin.
|
28
|
+
You could add a section containing default values like this:
|
29
|
+
|
30
|
+
#{tag_name}:
|
31
|
+
#{config_die_key}: false
|
32
|
+
END_MSG
|
33
|
+
else
|
34
|
+
<<~END_MSG
|
35
|
+
_config.yml contains the following configuration for this plugin is:
|
36
|
+
#{tag_config}
|
37
|
+
END_MSG
|
38
|
+
end
|
39
|
+
|
40
|
+
<<~END_MSG
|
41
|
+
Loaded plugin #{tag_name} v#{version}. It has:
|
42
|
+
Error class: #{error_ruby_class_name}
|
43
|
+
CSS class for error messages: #{error_css_class_name}
|
44
|
+
|
45
|
+
#{tag_config_msg}
|
46
|
+
END_MSG
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.register(klass, tag_name)
|
50
|
+
abort("Error: The #{tag_name} plugin does not define VERSION") \
|
16
51
|
unless klass.const_defined?(:VERSION)
|
17
52
|
|
18
53
|
version = klass.const_get(:VERSION)
|
19
54
|
|
20
|
-
abort("Error: The #{
|
55
|
+
abort("Error: The #{tag_name} plugin is not an instance of JekyllSupport::JekyllBlock or JekyllSupport::JekyllTag") \
|
21
56
|
unless klass.instance_of?(Class) &&
|
22
57
|
(klass.ancestors.include?(JekyllSupport::JekyllBlock) ||
|
23
58
|
klass.ancestors.include?(JekyllSupport::JekyllTag))
|
24
59
|
|
25
|
-
Liquid::Template.register_tag(
|
26
|
-
|
60
|
+
Liquid::Template.register_tag(tag_name, klass)
|
61
|
+
msg = generate_message(klass, tag_name, version)
|
62
|
+
PluginMetaLogger.instance.info msg
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.remove_html_tags(string)
|
66
|
+
string.gsub(/<[^>]*>/, '').strip
|
27
67
|
end
|
28
68
|
|
29
69
|
# strip leading and trailing quotes if present
|
@@ -8,6 +8,14 @@ module JekyllSupport
|
|
8
8
|
include JekyllSupportErrorHandling
|
9
9
|
extend JekyllSupportErrorHandling
|
10
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
|
+
|
11
19
|
# See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
|
12
20
|
# @param tag_name [String] the name of the tag, which we usually know.
|
13
21
|
# @param argument_string [String] the arguments passed to the tag, as a single string.
|
@@ -24,6 +32,9 @@ module JekyllSupport
|
|
24
32
|
@logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
|
25
33
|
@logger.debug { "#{self.class}: respond_to?(:no_arg_parsing) #{respond_to?(:no_arg_parsing) ? 'yes' : 'no'}." }
|
26
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
|
27
38
|
end
|
28
39
|
|
29
40
|
# Method prescribed by the Jekyll plugin lifecycle.
|
@@ -41,6 +52,8 @@ module JekyllSupport
|
|
41
52
|
@config = @site.config
|
42
53
|
@tag_config = @config[@tag_name]
|
43
54
|
|
55
|
+
set_error_context @error_name
|
56
|
+
|
44
57
|
@layout = @envs[:layout]
|
45
58
|
@paginator = @envs[:paginator]
|
46
59
|
@theme = @envs[:theme]
|
@@ -58,11 +71,15 @@ module JekyllSupport
|
|
58
71
|
render_impl text
|
59
72
|
rescue StandardError => e
|
60
73
|
e.shorten_backtrace
|
61
|
-
|
62
|
-
|
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
|
63
76
|
raise e if @die_on_standard_error
|
64
77
|
|
65
|
-
|
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
|
66
83
|
end
|
67
84
|
|
68
85
|
# Jekyll plugins should override this method, not render,
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative 'jekyll_custom_error'
|
2
|
+
|
1
3
|
# Monkey patch StandardError so a new method called shorten_backtrace is added.
|
2
4
|
class StandardError
|
3
5
|
def shorten_backtrace(backtrace_element_count = 3)
|
@@ -20,7 +22,7 @@ module JekyllSupport
|
|
20
22
|
|
21
23
|
# @return a new StandardError subclass containing the shorten_backtrace method
|
22
24
|
def define_error
|
23
|
-
Class.new
|
25
|
+
Class.new Jekyll::CustomError
|
24
26
|
end
|
25
27
|
module_function :define_error
|
26
28
|
|
@@ -78,7 +80,7 @@ module JekyllSupport
|
|
78
80
|
def self.warn_short_trace(logger, error)
|
79
81
|
remaining = error.backtrace.length - DISPLAYED_CALLS
|
80
82
|
logger.warn do
|
81
|
-
error.
|
83
|
+
error.message + "\n" +
|
82
84
|
error.backtrace.take(DISPLAYED_CALLS).join("\n") +
|
83
85
|
"\n...Remaining #{remaining} call sites elided.\n"
|
84
86
|
end
|
@@ -27,6 +27,17 @@ module JekyllSupport
|
|
27
27
|
@logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
|
28
28
|
@logger.debug { "#{self.class}: respond_to?(:no_arg_parsing) #{respond_to?(:no_arg_parsing) ? 'yes' : 'no'}." }
|
29
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)
|
30
41
|
end
|
31
42
|
|
32
43
|
# Method prescribed by the Jekyll plugin lifecycle.
|
@@ -45,6 +56,8 @@ module JekyllSupport
|
|
45
56
|
@jps = @config['jekyll_plugin_support']
|
46
57
|
@pry_on_standard_error = @jps['pry_on_standard_error'] || false if @jps
|
47
58
|
|
59
|
+
set_error_context @error_name
|
60
|
+
|
48
61
|
# @envs.keys are :content, :highlighter_prefix, :highlighter_suffix, :jekyll, :layout, :page, :paginator, :site, :theme
|
49
62
|
@layout = @envs[:layout]
|
50
63
|
@paginator = @envs[:paginator]
|
@@ -57,12 +70,15 @@ module JekyllSupport
|
|
57
70
|
render_impl
|
58
71
|
rescue StandardError => e
|
59
72
|
e.shorten_backtrace
|
60
|
-
|
61
|
-
@logger.error msg
|
73
|
+
@logger.error { "#{e.class} on line #{@line_number} of #{e.backtrace[0].split(':').first} while processing #{tag_name} - #{e.message}" }
|
62
74
|
binding.pry if @pry_on_standard_error # rubocop:disable Lint/Debugger
|
63
75
|
raise e if @die_on_standard_error
|
64
76
|
|
65
|
-
|
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
|
66
82
|
end
|
67
83
|
|
68
84
|
# Jekyll plugins must override this method, not render, so their plugin can be tested more easily
|
@@ -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
|
data/spec/status_persistence.txt
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
example_id | status | run_time |
|
2
2
|
------------------------------------------------ | ------ | --------------- |
|
3
|
-
./spec/jekyll_plugin_helper_options_spec.rb[1:1] |
|
4
|
-
./spec/jekyll_plugin_helper_options_spec.rb[1:2] |
|
5
|
-
./spec/jekyll_plugin_helper_options_spec.rb[1:3] |
|
6
|
-
./spec/jekyll_plugin_helper_options_spec.rb[1:4] |
|
7
|
-
./spec/liquid_variable_parsing_spec.rb[1:1] | failed | 0.00003 seconds |
|
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.8.
|
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:
|
11
|
+
date: 2024-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: facets
|
@@ -94,6 +94,7 @@ files:
|
|
94
94
|
- README.md
|
95
95
|
- Rakefile
|
96
96
|
- jekyll_plugin_support.gemspec
|
97
|
+
- lib/jekyll_custom_error.rb
|
97
98
|
- lib/jekyll_plugin_error_handling.rb
|
98
99
|
- lib/jekyll_plugin_helper.rb
|
99
100
|
- lib/jekyll_plugin_helper_attribution.rb
|
@@ -106,6 +107,7 @@ files:
|
|
106
107
|
- lib/jekyll_plugin_support_spec_support.rb
|
107
108
|
- lib/jekyll_plugin_support_tag.rb
|
108
109
|
- lib/jekyll_plugin_support_tag_noarg.rb
|
110
|
+
- spec/custom_error_spec.rb
|
109
111
|
- spec/jekyll_plugin_helper_options_spec.rb
|
110
112
|
- spec/liquid_variable_parsing_spec.rb
|
111
113
|
- spec/spec_helper.rb
|
@@ -137,11 +139,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
139
|
- !ruby/object:Gem::Version
|
138
140
|
version: '0'
|
139
141
|
requirements: []
|
140
|
-
rubygems_version: 3.
|
142
|
+
rubygems_version: 3.4.22
|
141
143
|
signing_key:
|
142
144
|
specification_version: 4
|
143
145
|
summary: Provides a framework for writing and testing Jekyll plugins
|
144
146
|
test_files:
|
147
|
+
- spec/custom_error_spec.rb
|
145
148
|
- spec/jekyll_plugin_helper_options_spec.rb
|
146
149
|
- spec/liquid_variable_parsing_spec.rb
|
147
150
|
- spec/spec_helper.rb
|