jekyll_plugin_support 0.8.6 → 1.0.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 +7 -4
- data/CHANGELOG.md +15 -0
- data/README.md +20 -5
- data/lib/block/jekyll_plugin_support_block.rb +3 -4
- data/lib/block/jekyll_plugin_support_block_noarg.rb +0 -3
- data/lib/error/jekyll_custom_error.rb +1 -1
- data/lib/error/jekyll_plugin_error_handling.rb +2 -4
- data/lib/generator/jekyll_plugin_support_generator.rb +1 -4
- data/lib/helper/jekyll_plugin_helper.rb +87 -85
- data/lib/helper/jekyll_plugin_helper_attribution.rb +60 -58
- data/lib/helper/jekyll_plugin_helper_class.rb +63 -61
- data/lib/jekyll_plugin_support/jekyll_plugin_support_class.rb +1 -1
- data/lib/jekyll_plugin_support/version.rb +1 -1
- data/lib/jekyll_plugin_support.rb +25 -0
- data/lib/tag/jekyll_plugin_support_tag.rb +4 -6
- data/lib/tag/jekyll_plugin_support_tag_noarg.rb +0 -3
- data/spec/custom_error_spec.rb +2 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eab3c711a499142ca58c0c2083dbac62072dd98f86dd343c57dda2d7603aed8b
|
4
|
+
data.tar.gz: 101b79a6402931862a23be32c12fd3a8152b56aa3644f38cd73a1a7d2bde9a2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a82cb83ce7c34268e79c0c4715832442cab58bd2e49a67ee849bf7d0fbd378bb068f0a5e499db9ccbace3567b04e95b5d0efd061a8d6f21a164a4ef6cc881efe
|
7
|
+
data.tar.gz: 0e6328a5b3e0fc4320c999cc88cfa13a92cacf5279027afe26bcff5f0dc9f56404f14747124b403bf417815282ac7025fd9fcf9e7e161aeb6bf6a54fd4d47571
|
data/.rubocop.yml
CHANGED
@@ -34,14 +34,14 @@ Metrics/AbcSize:
|
|
34
34
|
|
35
35
|
Metrics/BlockLength:
|
36
36
|
Exclude:
|
37
|
-
-
|
37
|
+
- jekyll_plugin_support.gemspec
|
38
38
|
Max: 30
|
39
39
|
|
40
40
|
Metrics/CyclomaticComplexity:
|
41
41
|
Max: 25
|
42
42
|
|
43
43
|
Metrics/MethodLength:
|
44
|
-
Max:
|
44
|
+
Max: 50
|
45
45
|
|
46
46
|
Metrics/PerceivedComplexity:
|
47
47
|
Max: 25
|
@@ -49,14 +49,17 @@ Metrics/PerceivedComplexity:
|
|
49
49
|
Naming/FileName:
|
50
50
|
Exclude:
|
51
51
|
- Rakefile
|
52
|
+
- "*.md"
|
52
53
|
|
53
54
|
RSpec/ExampleLength:
|
54
55
|
Max: 30
|
55
56
|
|
56
|
-
RSpec/
|
57
|
+
RSpec/SpecFilePathFormat:
|
57
58
|
Enabled: false
|
58
59
|
IgnoreMethods: true
|
59
|
-
|
60
|
+
|
61
|
+
RSpec/SpecFilePathSuffix:
|
62
|
+
Enabled: false
|
60
63
|
|
61
64
|
RSpec/IndexedLet:
|
62
65
|
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
3
|
|
4
|
+
## 1.0.1 / 2024-07-27
|
5
|
+
|
6
|
+
* Moved `warn_short_trace`, `maybe_reraise_error`, `remove_ansi_color`,
|
7
|
+
`format_error_message` and `exit_without_stack_trace` into `JekyllSupportError`.
|
8
|
+
* Added missing `shared_include.css` and `clippy.svg` to `demo/`.
|
9
|
+
* Fixed missing module name when invoking `format_error_message`.
|
10
|
+
|
11
|
+
|
12
|
+
## 1.0.0 / 2024-07-23
|
13
|
+
|
14
|
+
* Added the `redef_without_warning` method so tag and block plugins can be subclassed.
|
15
|
+
* Put most of the functionality into the `JekyllSupport` module.
|
16
|
+
* Made tag and block code more consistent
|
17
|
+
|
18
|
+
|
4
19
|
## 0.8.6 / 2024-06-11
|
5
20
|
|
6
21
|
* Fixup version, containing what was supposed to be in v0.8.5
|
data/README.md
CHANGED
@@ -55,9 +55,9 @@ add the following line to your Jekyll plugin’s `Gemfile`.
|
|
55
55
|
|
56
56
|
```ruby
|
57
57
|
group :jekyll_plugins do
|
58
|
-
...
|
58
|
+
# ...
|
59
59
|
gem 'jekyll_plugin_support', '>= 0.8.0'
|
60
|
-
...
|
60
|
+
# ...
|
61
61
|
end
|
62
62
|
```
|
63
63
|
|
@@ -65,9 +65,9 @@ Otherwise, if your custom plugin will be packaged into a gem, add the following
|
|
65
65
|
|
66
66
|
```ruby
|
67
67
|
Gem::Specification.new do |spec|
|
68
|
-
...
|
68
|
+
# ...
|
69
69
|
spec.add_dependency 'jekyll_plugin_support', '>= 0.8.0'
|
70
|
-
...
|
70
|
+
# ...
|
71
71
|
end
|
72
72
|
```
|
73
73
|
|
@@ -516,7 +516,7 @@ without tokenization, and you expect that the plugin might be invoked with large
|
|
516
516
|
derive your plugin from `JekyllBlockNoArgParsing` or `JekyllTagNoArgParsing`.
|
517
517
|
|
518
518
|
|
519
|
-
##
|
519
|
+
## Attribution
|
520
520
|
|
521
521
|
`JekyllTag` and `JekyllBlock` subclasses of `jekyll_plugin_support` can utilize the `attribution`
|
522
522
|
option if they are published as a gem.
|
@@ -584,6 +584,21 @@ An alternative attribution string can be specified properties can be output usin
|
|
584
584
|
{% my_tag attribution="Generated by the #{name} #{version} Jekyll plugin, written by #{author} #{date}" %}
|
585
585
|
```
|
586
586
|
|
587
|
+
## Subclassing
|
588
|
+
|
589
|
+
Jekyll plugins created using `jekyll_plugin_support` are implemented as Ruby classes.
|
590
|
+
If you would like to create a version of an existing Jekyll plugin, you will need to subclass the plugin.
|
591
|
+
In order to do that, you will need to override the plugin name and version, which are defined as constants.
|
592
|
+
|
593
|
+
`Jekyll_plugin_support` provides a method that allows
|
594
|
+
a constant to be redefined, called `redef_without_warning`.
|
595
|
+
Use it in a subclass like this:
|
596
|
+
|
597
|
+
```ruby
|
598
|
+
redef_without_warning :PLUGIN_NAME, 'my_plugin'.freeze
|
599
|
+
redef_without_warning :VERSION, '0.1.0'.freeze
|
600
|
+
```
|
601
|
+
|
587
602
|
|
588
603
|
## Development
|
589
604
|
|
@@ -5,9 +5,6 @@ module JekyllSupport
|
|
5
5
|
class JekyllBlock < Liquid::Block
|
6
6
|
attr_reader :argument_string, :helper, :line_number, :logger, :page, :site, :text
|
7
7
|
|
8
|
-
include JekyllSupportErrorHandling
|
9
|
-
extend JekyllSupportErrorHandling
|
10
|
-
|
11
8
|
# See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
|
12
9
|
# @param tag_name [String] the name of the tag, which we usually know.
|
13
10
|
# @param argument_string [String] the arguments passed to the tag, as a single string.
|
@@ -26,7 +23,7 @@ module JekyllSupport
|
|
26
23
|
@helper = JekyllPluginHelper.new tag_name, markup, @logger, respond_to?(:no_arg_parsing)
|
27
24
|
|
28
25
|
@error_name = "#{tag_name.camelcase(:upper)}Error"
|
29
|
-
|
26
|
+
JekyllSupport::CustomError.factory @error_name
|
30
27
|
end
|
31
28
|
|
32
29
|
# Liquid::Block subclasses do not render if there is no content within the tag
|
@@ -49,6 +46,8 @@ module JekyllSupport
|
|
49
46
|
|
50
47
|
@config = @site.config
|
51
48
|
@tag_config = @config[@tag_name]
|
49
|
+
@jps = @config['jekyll_plugin_support']
|
50
|
+
@pry_on_standard_error = @jps['pry_on_standard_error'] || false if @jps
|
52
51
|
|
53
52
|
set_error_context
|
54
53
|
|
@@ -4,9 +4,6 @@ module JekyllSupport
|
|
4
4
|
class JekyllBlockNoArgParsing < JekyllBlock
|
5
5
|
attr_reader :argument_string, :helper, :line_number, :logger, :page, :site
|
6
6
|
|
7
|
-
include JekyllSupportErrorHandling
|
8
|
-
extend JekyllSupportErrorHandling
|
9
|
-
|
10
7
|
def initialize(tag_name, argument_string, parse_context)
|
11
8
|
class << self
|
12
9
|
include NoArgParsing
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module JekyllSupportError
|
2
2
|
attr_reader :logger, :page
|
3
3
|
|
4
4
|
# If a Jekyll plugin needs to crash exit, and stop Jekyll, call this method.
|
@@ -24,19 +24,17 @@ module JekyllSupportErrorHandling
|
|
24
24
|
exec "echo ''"
|
25
25
|
end
|
26
26
|
|
27
|
-
# TODO: Delete this
|
28
27
|
def format_error_message(message)
|
29
28
|
page = " of #{@page['path']}" if @page
|
30
29
|
remove_ansi_color "on line #{line_number} (after front matter)#{page}.\n#{message}"
|
31
30
|
end
|
32
31
|
|
33
|
-
# TODO: Delete this
|
34
32
|
def remove_ansi_color(string)
|
35
33
|
string.gsub(/\e\[([;\d]+)?m/, '')
|
36
34
|
end
|
37
35
|
|
38
36
|
def maybe_reraise_error(error, throw_error: true)
|
39
|
-
fmsg = format_error_message "#{error.class}: #{error.message.strip}"
|
37
|
+
fmsg = JekyllSupport.format_error_message "#{error.class}: #{error.message.strip}"
|
40
38
|
@logger.error { fmsg }
|
41
39
|
return "<span class='jekyll_plugin_support_error'>#{fmsg}</span>" unless throw_error
|
42
40
|
|
@@ -7,9 +7,6 @@ module JekyllSupport
|
|
7
7
|
class JekyllGenerator < Jekyll::Generator
|
8
8
|
attr_reader :helper, :line_number, :logger, :site
|
9
9
|
|
10
|
-
include JekyllSupportErrorHandling
|
11
|
-
extend JekyllSupportErrorHandling
|
12
|
-
|
13
10
|
# Method prescribed by the Jekyll plugin lifecycle.
|
14
11
|
# Defines @config, @envs, @mode and @site
|
15
12
|
# @return [void]
|
@@ -17,7 +14,7 @@ module JekyllSupport
|
|
17
14
|
@logger ||= PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
|
18
15
|
|
19
16
|
@error_name = "#{self.class.name}Error"
|
20
|
-
#
|
17
|
+
# JekyllSupport::CustomError.factory @error_name
|
21
18
|
|
22
19
|
@site = site
|
23
20
|
@config = @site.config
|
@@ -4,107 +4,109 @@ require 'shellwords'
|
|
4
4
|
require_relative 'jekyll_plugin_helper_class'
|
5
5
|
require_relative 'jekyll_plugin_helper_attribution'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
e
|
28
|
-
|
29
|
-
|
7
|
+
module JekyllSupport
|
8
|
+
class JekyllPluginHelper
|
9
|
+
attr_accessor :liquid_context
|
10
|
+
attr_reader :argv, :attribution, :keys_values, :logger, :markup, :no_arg_parsing, :params, :tag_name,
|
11
|
+
:argv_original, :excerpt_caller, :keys_values_original, :params_original, :jpsh_subclass_caller
|
12
|
+
|
13
|
+
# See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
|
14
|
+
# @param tag_name [String] the name of the tag, which we already know.
|
15
|
+
# @param argument_string [String] the arguments from the tag, as a single string.
|
16
|
+
# @param parse_context [Liquid::ParseContext] hash that stores Liquid options.
|
17
|
+
# By default it has two keys: :locale and :line_numbers, the first is a Liquid::I18n object, and the second,
|
18
|
+
# a boolean parameter that determines if error messages should display the line number the error occurred.
|
19
|
+
# This argument is used mostly to display localized error messages on Liquid built-in Tags and Filters.
|
20
|
+
# See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
|
21
|
+
# @return [void]
|
22
|
+
def initialize(tag_name, markup, logger, no_arg_parsing)
|
23
|
+
@tag_name = tag_name
|
24
|
+
@logger = logger
|
25
|
+
@no_arg_parsing = no_arg_parsing
|
26
|
+
@markup = markup
|
27
|
+
rescue StandardError => e
|
28
|
+
e.shorten_backtrace
|
29
|
+
@logger.error { e.message }
|
30
|
+
end
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
# @return undefined if parameter was specified, removes it from the available tokens and returns value
|
33
|
+
def parameter_specified?(name, delete_param: true)
|
34
|
+
return false if @keys_values.to_s.empty?
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
key = name
|
37
|
+
key = name.to_sym if @keys_values&.first&.first.instance_of?(Symbol)
|
38
|
+
value = @keys_values[key]
|
39
|
+
delete_parameter(name) if delete_param
|
40
|
+
value
|
41
|
+
end
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
43
|
+
def reinitialize(markup)
|
44
|
+
# @keys_values was a Hash[Symbol, String|Boolean] but now it is Hash[String, String|Boolean]
|
45
|
+
@markup = markup
|
46
|
+
if @no_arg_parsing
|
47
|
+
define_singleton_method(:argv) { warn_fetch :argv }
|
48
|
+
define_singleton_method(:keys_values) { warn_fetch :keys_values }
|
49
|
+
define_singleton_method(:params) { warn_fetch :params }
|
50
|
+
define_singleton_method(:parameter_specified?) { |_name| warn_parse(:parameter_specified?) }
|
51
|
+
define_singleton_method(:delete_parameter) { |_name| warn_parse(:delete_parameter) }
|
52
|
+
@attribution = false
|
53
|
+
else
|
54
|
+
parse markup
|
55
|
+
@attribution = parameter_specified?('attribution') || false
|
56
|
+
@logger.debug { "@keys_values='#{@keys_values}'" }
|
57
|
+
end
|
56
58
|
end
|
57
|
-
end
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
# Call this method to return the remaining markup after `parameter_specified?` has been invoked.
|
61
|
+
def remaining_markup
|
62
|
+
@argv&.join(' ')
|
63
|
+
end
|
63
64
|
|
64
|
-
|
65
|
-
|
66
|
-
|
65
|
+
def remaining_markup_original
|
66
|
+
@argv_original&.join(' ')
|
67
|
+
end
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
|
69
|
+
def warn_fetch(variable)
|
70
|
+
abort "Error: Argument parsing was suppressed, but an attempt to obtain the value of #{variable} was made"
|
71
|
+
end
|
71
72
|
|
72
|
-
|
73
|
-
|
74
|
-
|
73
|
+
def warn_parse(meth)
|
74
|
+
abort "Error: Argument parsing was suppressed, but an attempt to invoke #{meth} was made"
|
75
|
+
end
|
75
76
|
|
76
|
-
|
77
|
-
|
77
|
+
def delete_parameter(key)
|
78
|
+
return if @keys_values.empty? || @params.nil?
|
78
79
|
|
79
|
-
|
80
|
-
|
81
|
-
|
80
|
+
@params.delete(key)
|
81
|
+
@argv.delete_if { |x| x == key or x.start_with?("#{key}=") }
|
82
|
+
@keys_values.delete(key)
|
82
83
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
84
|
+
@params_original.delete(key)
|
85
|
+
@argv_original.delete_if { |x| x == key or x.start_with?("#{key}=") }
|
86
|
+
@keys_values_original.delete(key)
|
87
|
+
end
|
87
88
|
|
88
|
-
|
89
|
+
private
|
89
90
|
|
90
|
-
|
91
|
-
|
92
|
-
|
91
|
+
def page
|
92
|
+
@liquid_context.registers[:page]
|
93
|
+
end
|
93
94
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
95
|
+
def parse(markup)
|
96
|
+
@argv_original = Shellwords.split(markup)
|
97
|
+
@keys_values_original = KeyValueParser
|
98
|
+
.new({}, { array_values: false, normalize_keys: false, separator: /=/ })
|
99
|
+
.parse(@argv_original)
|
100
|
+
@params_original = @keys_values_original unless respond_to?(:no_arg_parsing) && no_arg_parsing
|
100
101
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
102
|
+
@argv = Shellwords.split(self.class.expand_env(markup, logger))
|
103
|
+
@keys_values = KeyValueParser
|
104
|
+
.new({}, { array_values: false, normalize_keys: false, separator: /=/ })
|
105
|
+
.parse(@argv)
|
105
106
|
|
106
|
-
|
107
|
+
return if respond_to?(:no_arg_parsing) && no_arg_parsing
|
107
108
|
|
108
|
-
|
109
|
+
@params = @keys_values # TODO: @keys_values should be deleted
|
110
|
+
end
|
109
111
|
end
|
110
112
|
end
|
@@ -1,72 +1,74 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
1
|
+
module JekyllSupport
|
2
|
+
# Attribution aspect of JekyllPluginHelper
|
3
|
+
class JekyllPluginHelper
|
4
|
+
# @param file must be a fully qualified file name that points to a file within a gem.
|
5
|
+
# @return Gem::Specification of gem that file points into, or nil if not called from a gem
|
6
|
+
# See https://stackoverflow.com/a/75890279/553865
|
7
|
+
def self.current_spec(file)
|
8
|
+
abort 'JekyllPluginHelper::current_spec: file is nil' if file.nil?
|
9
|
+
return nil unless File.exist?(file)
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
searcher = if Gem::Specification.respond_to?(:find)
|
12
|
+
Gem::Specification
|
13
|
+
elsif Gem.respond_to?(:searcher)
|
14
|
+
Gem.searcher.init_gemspecs
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
searcher&.find do |spec|
|
18
|
+
file.start_with? spec.full_gem_path
|
19
|
+
end
|
18
20
|
end
|
19
|
-
end
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
def attribute
|
23
|
+
return unless @current_gem
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
<<~END_OUTPUT
|
26
|
+
<div id="jps_attribute_#{rand(999_999)}" class="jps_attribute">
|
27
|
+
<div>
|
28
|
+
<a href="#{@homepage}" target="_blank" rel="nofollow">
|
29
|
+
#{attribution_string}
|
30
|
+
</a>
|
31
|
+
</div>
|
30
32
|
</div>
|
31
|
-
|
32
|
-
|
33
|
-
end
|
33
|
+
END_OUTPUT
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
def default_attribution
|
37
|
+
authors = @authors&.join(', ')
|
38
|
+
result = "Generated by the \#{@name} v\#{@version} Jekyll plugin"
|
39
|
+
result << ", written by #{authors}" if authors
|
40
|
+
result << " \#{@published_date}" if @published_date
|
41
|
+
result << '.'
|
42
|
+
result
|
43
|
+
end
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
# Sets @current_gem if file points at a uniquely named file within a gem.
|
46
|
+
# @param file must be a fully qualified file name in a gem, for example: __FILE__
|
47
|
+
def gem_file(file)
|
48
|
+
@current_gem = JekyllPluginHelper.current_spec file
|
49
|
+
@logger.debug "No gem found for '#{file} was found." unless @current_gem
|
50
|
+
annotate_globals if @attribution && @current_gem
|
51
|
+
end
|
51
52
|
|
52
|
-
|
53
|
+
private
|
53
54
|
|
54
|
-
|
55
|
-
|
55
|
+
def annotate_globals
|
56
|
+
return unless @current_gem
|
56
57
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
58
|
+
@name = @current_gem.name
|
59
|
+
@authors = @current_gem.authors
|
60
|
+
@homepage = @current_gem.homepage
|
61
|
+
@published_date = @current_gem.date.to_date.to_s
|
62
|
+
@version = @current_gem.version
|
63
|
+
end
|
63
64
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
65
|
+
def attribution_string
|
66
|
+
string = if @attribution == true
|
67
|
+
default_attribution
|
68
|
+
else
|
69
|
+
@attribution
|
70
|
+
end
|
71
|
+
String.interpolate { string }
|
72
|
+
end
|
71
73
|
end
|
72
74
|
end
|
@@ -2,80 +2,82 @@ require 'facets/string/camelcase'
|
|
2
2
|
require 'facets/string/snakecase'
|
3
3
|
require 'yaml'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
str
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
module JekyllSupport
|
6
|
+
# Class methods for JekyllPluginHelper
|
7
|
+
class JekyllPluginHelper
|
8
|
+
# Expand an environment variable reference
|
9
|
+
def self.expand_env(str, logger = nil, die_if_undefined: false)
|
10
|
+
str&.gsub(/\$([a-zA-Z_][a-zA-Z0-9_]*)|\${\g<1>}/) do
|
11
|
+
envar = Regexp.last_match(1)
|
12
|
+
unless ENV.key? envar
|
13
|
+
msg = "jekyll_plugin_support error: environment variable #{envar} is undefined"
|
14
|
+
raise JekyllPluginSupportError, msg.red, [] if die_if_undefined
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
if logger
|
17
|
+
logger.warn msg
|
18
|
+
else
|
19
|
+
puts msg.red
|
20
|
+
end
|
19
21
|
end
|
22
|
+
ENV.fetch(envar, nil)
|
20
23
|
end
|
21
|
-
ENV.fetch(envar, nil)
|
22
24
|
end
|
23
|
-
end
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
26
|
+
def self.generate_message(klass, tag_name, version)
|
27
|
+
error_name_stub = klass.name.include?('::') ? klass.name.split('::')[1] : klass.name
|
28
|
+
error_ruby_class_name = "#{error_name_stub.camelcase(:upper)}Error"
|
29
|
+
config_die_key = "die_on_#{error_ruby_class_name.snakecase}"
|
30
|
+
error_css_class_name = error_ruby_class_name.split('::').last.snakecase
|
31
|
+
config = YAML.load_file('_config.yml')
|
32
|
+
tag_config = config[tag_name]
|
33
|
+
tag_config_msg = if tag_config.nil?
|
34
|
+
<<~END_MSG
|
35
|
+
_config.yml does not contain configuration information for this plugin.
|
36
|
+
You could add a section containing default values by specifying a section for the tag name,
|
37
|
+
and an entry whose name starts with `die_on_`, followed by a snake_case version of the error name.
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
39
|
+
#{tag_name}:
|
40
|
+
#{config_die_key}: false
|
41
|
+
END_MSG
|
42
|
+
else
|
43
|
+
<<~END_MSG
|
44
|
+
_config.yml contains the following configuration for this plugin:
|
45
|
+
#{tag_config}
|
46
|
+
END_MSG
|
47
|
+
end
|
47
48
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
<<~END_MSG
|
50
|
+
Loaded plugin #{tag_name} v#{version}. It has:
|
51
|
+
Error class: #{error_ruby_class_name}
|
52
|
+
CSS class for error messages: #{error_css_class_name}
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
|
54
|
+
#{tag_config_msg}
|
55
|
+
END_MSG
|
56
|
+
end
|
56
57
|
|
57
|
-
|
58
|
-
|
59
|
-
|
58
|
+
def self.register(klass, tag_name)
|
59
|
+
abort("Error: The #{tag_name} plugin does not define VERSION") \
|
60
|
+
unless klass.const_defined?(:VERSION)
|
60
61
|
|
61
|
-
|
62
|
+
version = klass.const_get(:VERSION)
|
62
63
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
64
|
+
abort("Error: The #{tag_name} plugin is not an instance of JekyllSupport::JekyllBlock or JekyllSupport::JekyllTag") \
|
65
|
+
unless klass.instance_of?(Class) &&
|
66
|
+
(klass.ancestors.include?(JekyllSupport::JekyllBlock) ||
|
67
|
+
klass.ancestors.include?(JekyllSupport::JekyllTag))
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
Liquid::Template.register_tag(tag_name, klass)
|
70
|
+
msg = generate_message(klass, tag_name, version)
|
71
|
+
PluginMetaLogger.instance.info { msg }
|
72
|
+
end
|
72
73
|
|
73
|
-
|
74
|
-
|
75
|
-
|
74
|
+
def self.remove_html_tags(string)
|
75
|
+
string.gsub(/<[^>]*>/, '').strip
|
76
|
+
end
|
76
77
|
|
77
|
-
|
78
|
-
|
79
|
-
|
78
|
+
# strip leading and trailing quotes if present
|
79
|
+
def self.remove_quotes(string)
|
80
|
+
string.strip.gsub(/\A'|\A"|'\Z|"\Z/, '').strip if string
|
81
|
+
end
|
80
82
|
end
|
81
83
|
end
|
@@ -8,6 +8,13 @@ def require_directory(dir)
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
module JekyllSupport
|
12
|
+
def self.redef_without_warning(const, value)
|
13
|
+
send(:remove_const, const) if const_defined?(const)
|
14
|
+
const_set const, value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
11
18
|
module NoArgParsing
|
12
19
|
attr_accessor :no_arg_parsing
|
13
20
|
|
@@ -21,3 +28,21 @@ require_directory "#{__dir__}/generator"
|
|
21
28
|
require_directory "#{__dir__}/helper"
|
22
29
|
require_directory "#{__dir__}/jekyll_plugin_support"
|
23
30
|
require_directory "#{__dir__}/tag"
|
31
|
+
|
32
|
+
module JekyllSupport
|
33
|
+
class JekyllTag
|
34
|
+
include JekyllSupportError
|
35
|
+
end
|
36
|
+
|
37
|
+
class JekyllTagNoArgParsing
|
38
|
+
include JekyllSupportError
|
39
|
+
end
|
40
|
+
|
41
|
+
class JekyllBlock
|
42
|
+
include JekyllSupportError
|
43
|
+
end
|
44
|
+
|
45
|
+
class JekyllBlockNoArgParsing
|
46
|
+
include JekyllSupportError
|
47
|
+
end
|
48
|
+
end
|
@@ -6,9 +6,6 @@ module JekyllSupport
|
|
6
6
|
class JekyllTag < Liquid::Tag
|
7
7
|
attr_reader :argument_string, :helper, :line_number, :logger, :page, :site
|
8
8
|
|
9
|
-
include JekyllSupportErrorHandling
|
10
|
-
extend JekyllSupportErrorHandling
|
11
|
-
|
12
9
|
# See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
|
13
10
|
# @param tag_name [String] the name of the tag, which we usually know.
|
14
11
|
# @param argument_string [String] the arguments passed to the tag, as a single string.
|
@@ -29,7 +26,7 @@ module JekyllSupport
|
|
29
26
|
@helper = JekyllPluginHelper.new(tag_name, @argument_string, @logger, respond_to?(:no_arg_parsing))
|
30
27
|
|
31
28
|
@error_name = "#{tag_name.camelcase(:upper)}Error"
|
32
|
-
|
29
|
+
JekyllSupport::CustomError.factory @error_name
|
33
30
|
end
|
34
31
|
|
35
32
|
# Method prescribed by the Jekyll plugin lifecycle.
|
@@ -55,10 +52,11 @@ module JekyllSupport
|
|
55
52
|
@paginator = @envs[:paginator]
|
56
53
|
@theme = @envs[:theme]
|
57
54
|
|
58
|
-
|
55
|
+
env = @config['env']
|
56
|
+
@mode = env&.key?('JEKYLL_ENV') ? env['JEKYLL_ENV'] : 'development'
|
59
57
|
|
60
58
|
markup = JekyllSupport.lookup_liquid_variables liquid_context, @argument_string
|
61
|
-
@helper.reinitialize markup
|
59
|
+
@helper.reinitialize markup.strip
|
62
60
|
|
63
61
|
render_impl
|
64
62
|
rescue StandardError => e
|
@@ -4,9 +4,6 @@ module JekyllSupport
|
|
4
4
|
class JekyllTagNoArgParsing < JekyllTag
|
5
5
|
attr_reader :argument_string, :helper, :line_number, :logger, :page, :site
|
6
6
|
|
7
|
-
include JekyllSupportErrorHandling
|
8
|
-
extend JekyllSupportErrorHandling
|
9
|
-
|
10
7
|
def initialize(tag_name, argument_string, parse_context)
|
11
8
|
class << self
|
12
9
|
include NoArgParsing
|
data/spec/custom_error_spec.rb
CHANGED
@@ -17,7 +17,7 @@ class CustomErrorSpec
|
|
17
17
|
raise AnError, 'Oops'
|
18
18
|
rescue AnError => e
|
19
19
|
puts "Caught AnError: #{e.message}"
|
20
|
-
rescue
|
20
|
+
rescue JekyllSupport::CustomError => e
|
21
21
|
puts "Caught CustomError: #{e.message}"
|
22
22
|
end
|
23
23
|
|
@@ -31,7 +31,7 @@ class CustomErrorSpec
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
RSpec.describe
|
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
|
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.
|
4
|
+
version: 1.0.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: 2024-
|
11
|
+
date: 2024-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: facets
|
@@ -140,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
140
|
- !ruby/object:Gem::Version
|
141
141
|
version: '0'
|
142
142
|
requirements: []
|
143
|
-
rubygems_version: 3.5.
|
143
|
+
rubygems_version: 3.5.16
|
144
144
|
signing_key:
|
145
145
|
specification_version: 4
|
146
146
|
summary: Provides a framework for writing and testing Jekyll plugins
|