jekyll_plugin_support 0.8.5 → 1.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -4
- data/CHANGELOG.md +11 -0
- data/README.md +20 -5
- data/lib/{jekyll_plugin_support_block.rb → block/jekyll_plugin_support_block.rb} +8 -8
- data/lib/{jekyll_plugin_support_block_noarg.rb → block/jekyll_plugin_support_block_noarg.rb} +7 -4
- data/lib/{jekyll_custom_error.rb → error/jekyll_custom_error.rb} +1 -1
- data/lib/{jekyll_plugin_error_handling.rb → error/jekyll_plugin_error_handling.rb} +1 -1
- data/lib/generator/jekyll_plugin_support_generator.rb +75 -0
- data/lib/helper/jekyll_plugin_helper.rb +112 -0
- data/lib/helper/jekyll_plugin_helper_attribution.rb +74 -0
- data/lib/helper/jekyll_plugin_helper_class.rb +83 -0
- data/lib/{jekyll_plugin_support_class.rb → jekyll_plugin_support/jekyll_plugin_support_class.rb} +2 -2
- data/lib/jekyll_plugin_support/version.rb +1 -1
- data/lib/jekyll_plugin_support.rb +20 -8
- data/lib/{jekyll_plugin_support_tag.rb → tag/jekyll_plugin_support_tag.rb} +5 -7
- data/lib/{jekyll_plugin_support_tag_noarg.rb → tag/jekyll_plugin_support_tag_noarg.rb} +1 -4
- data/spec/custom_error_spec.rb +2 -2
- metadata +15 -14
- data/lib/jekyll_plugin_helper.rb +0 -110
- data/lib/jekyll_plugin_helper_attribution.rb +0 -72
- data/lib/jekyll_plugin_helper_class.rb +0 -81
- /data/lib/{jekyll_plugin_support_spec_support.rb → jekyll_plugin_support/jekyll_plugin_support_spec_support.rb} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb346f630f3f3d54d602c2c130ead054765b3f1fcd5d2a13550a82d850ce6c7f
|
4
|
+
data.tar.gz: 50a247655dbdb650eaeabb6163843b2d9f2c1ec47c69609f43b0e22df10d96c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3277bc67de6688e3c4af585940a26bd641d157a54be0757a34aae364454fc5bfe952cb5e7834d8dc57eda4e6957ce1c1adcf603915d3bff442e7a88e52552ca
|
7
|
+
data.tar.gz: f9e68b39c8de0fa100d720601b59e2a052a8fb3de9746ccb7a37fa28752bb43171827dd325f7b1e6bda920561716feed78a69e477d1fc022832ff43ce5d9234a
|
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,5 +1,16 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 1.0.0 / 2024-07-23
|
4
|
+
|
5
|
+
* Added the `redef_without_warning` method so tag and block plugins can be subclassed.
|
6
|
+
* Put most of the functionality into the `JekyllSupport` module.
|
7
|
+
* Made tag and block code more consistent
|
8
|
+
|
9
|
+
|
10
|
+
## 0.8.6 / 2024-06-11
|
11
|
+
|
12
|
+
* Fixup version, containing what was supposed to be in v0.8.5
|
13
|
+
|
3
14
|
|
4
15
|
## 0.8.5 / 2024-03-25
|
5
16
|
|
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
|
|
@@ -1,13 +1,10 @@
|
|
1
|
-
require_relative 'jekyll_plugin_error_handling'
|
1
|
+
require_relative '../error/jekyll_plugin_error_handling'
|
2
2
|
|
3
3
|
module JekyllSupport
|
4
4
|
# Base class for Jekyll block tags
|
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
|
|
@@ -56,7 +55,8 @@ module JekyllSupport
|
|
56
55
|
@paginator = @envs[:paginator]
|
57
56
|
@theme = @envs[:theme]
|
58
57
|
|
59
|
-
|
58
|
+
env = @config['env']
|
59
|
+
@mode = env&.key?('JEKYLL_ENV') ? env['JEKYLL_ENV'] : 'development'
|
60
60
|
|
61
61
|
@helper.reinitialize @markup.strip
|
62
62
|
|
@@ -69,13 +69,13 @@ module JekyllSupport
|
|
69
69
|
render_impl(text)
|
70
70
|
rescue StandardError => e
|
71
71
|
e.shorten_backtrace
|
72
|
-
@logger.error { "#{e.class} on line #{@line_number} of #{e.backtrace[0].split(':').first} by #{tag_name} - #{e.message}" }
|
72
|
+
@logger.error { "#{e.class} on line #{@line_number} of #{e.backtrace[0].split(':').first} by #{@tag_name} - #{e.message}" }
|
73
73
|
binding.pry if @pry_on_standard_error # rubocop:disable Lint/Debugger
|
74
74
|
raise e if @die_on_standard_error
|
75
75
|
|
76
76
|
<<~END_MSG
|
77
77
|
<div class='standard_error'>
|
78
|
-
#{e.class} on line #{@line_number} of #{e.backtrace[0].split(':').first} by #{tag_name}: #{e.message}
|
78
|
+
#{e.class} on line #{@line_number} of #{e.backtrace[0].split(':').first} by #{@tag_name}: #{e.message}
|
79
79
|
</div>
|
80
80
|
END_MSG
|
81
81
|
end
|
data/lib/{jekyll_plugin_support_block_noarg.rb → block/jekyll_plugin_support_block_noarg.rb}
RENAMED
@@ -1,12 +1,9 @@
|
|
1
|
-
require_relative 'jekyll_plugin_error_handling'
|
1
|
+
require_relative '../error/jekyll_plugin_error_handling'
|
2
2
|
|
3
3
|
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
|
@@ -20,6 +17,12 @@ module JekyllSupport
|
|
20
17
|
JekyllSupport.error_short_trace(@logger, e)
|
21
18
|
end
|
22
19
|
|
20
|
+
# Liquid::Block subclasses do not render if there is no content within the tag
|
21
|
+
# This override fixes that
|
22
|
+
def blank?
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
23
26
|
# Jekyll plugins must override this method, not render, so their plugin can be tested more easily
|
24
27
|
# The following variables are predefined:
|
25
28
|
# @argument_string, @config, @envs, @helper, @layout, @logger, @mode, @page, @paginator, @site, @tag_name and @theme
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'jekyll'
|
2
|
+
require_relative '../error/jekyll_plugin_error_handling'
|
3
|
+
|
4
|
+
module JekyllSupport
|
5
|
+
# Base class for Jekyll generators.
|
6
|
+
# PluginMetaLogger.instance.config is populated with the contents of `_config.yml` before Jekyll::Generator instances run.
|
7
|
+
class JekyllGenerator < Jekyll::Generator
|
8
|
+
attr_reader :helper, :line_number, :logger, :site
|
9
|
+
|
10
|
+
# Method prescribed by the Jekyll plugin lifecycle.
|
11
|
+
# Defines @config, @envs, @mode and @site
|
12
|
+
# @return [void]
|
13
|
+
def generate(site)
|
14
|
+
@logger ||= PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
|
15
|
+
|
16
|
+
@error_name = "#{self.class.name}Error"
|
17
|
+
# JekyllSupport::CustomError.factory @error_name
|
18
|
+
|
19
|
+
@site = site
|
20
|
+
@config = @site.config
|
21
|
+
@envs = site.config['env']
|
22
|
+
@theme = @site.theme
|
23
|
+
|
24
|
+
@mode = ENV['JEKYLL_ENV'] || 'development'
|
25
|
+
|
26
|
+
# set_error_context(self.class)
|
27
|
+
|
28
|
+
generate_impl
|
29
|
+
rescue StandardError => e
|
30
|
+
e.shorten_backtrace
|
31
|
+
@logger.error { "#{e.class} on line #{@line_number} of #{e.backtrace[0].split(':').first} by #{self.class.name} - #{e.message}" }
|
32
|
+
binding.pry if @pry_on_standard_error # rubocop:disable Lint/Debugger
|
33
|
+
raise e if @die_on_standard_error
|
34
|
+
|
35
|
+
<<~END_MSG
|
36
|
+
<div class='standard_error'>
|
37
|
+
#{e.class} on line #{@line_number} of #{e.backtrace[0].split(':').first} by #{self.class.name}: #{e.message}
|
38
|
+
</div>
|
39
|
+
END_MSG
|
40
|
+
end
|
41
|
+
|
42
|
+
# Jekyll plugins should override this method, not `generate`, so they can be tested more easily.
|
43
|
+
# The following variables are predefined:
|
44
|
+
# @config, @envs, @helper, @logger, @mode, @paginator, @site and @theme
|
45
|
+
# @return [void]
|
46
|
+
def generate_impl; end
|
47
|
+
|
48
|
+
def self.register(klass)
|
49
|
+
abort("Error: The #{klass.name} plugin does not define VERSION") \
|
50
|
+
unless klass.const_defined?(:VERSION)
|
51
|
+
|
52
|
+
version = klass.const_get(:VERSION)
|
53
|
+
error_name_stub = klass.name.include?('::') ? klass.name.split('::')[1] : klass.name
|
54
|
+
error_ruby_class_name = "#{error_name_stub.camelcase(:upper)}Error"
|
55
|
+
error_css_class_name = error_ruby_class_name.split('::').last.snakecase
|
56
|
+
msg = <<~END_MSG
|
57
|
+
Loaded generator plugin #{klass.name} v#{version}. It has:
|
58
|
+
Error class: #{@error_name}
|
59
|
+
CSS class for error messages: #{error_css_class_name}
|
60
|
+
END_MSG
|
61
|
+
|
62
|
+
PluginMetaLogger.instance.info { msg }
|
63
|
+
end
|
64
|
+
|
65
|
+
def set_error_context(klass)
|
66
|
+
return unless Object.const_defined? @error_name
|
67
|
+
|
68
|
+
error_class = Object.const_get @error_name
|
69
|
+
error_class.class_variable_set(:@@argument_string, @argument_string)
|
70
|
+
error_class.class_variable_set(:@@line_number, @line_number)
|
71
|
+
error_class.class_variable_set(:@@path, @page['path'])
|
72
|
+
error_class.class_variable_set(:@@tag_name, klass.name)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'facets/string/interpolate'
|
2
|
+
require 'key_value_parser'
|
3
|
+
require 'shellwords'
|
4
|
+
require_relative 'jekyll_plugin_helper_class'
|
5
|
+
require_relative 'jekyll_plugin_helper_attribution'
|
6
|
+
|
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
|
31
|
+
|
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?
|
35
|
+
|
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
|
42
|
+
|
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
|
58
|
+
end
|
59
|
+
|
60
|
+
# Call this method to return the remaining markup after `parameter_specified?` has been invoked.
|
61
|
+
def remaining_markup
|
62
|
+
@argv&.join(' ')
|
63
|
+
end
|
64
|
+
|
65
|
+
def remaining_markup_original
|
66
|
+
@argv_original&.join(' ')
|
67
|
+
end
|
68
|
+
|
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
|
72
|
+
|
73
|
+
def warn_parse(meth)
|
74
|
+
abort "Error: Argument parsing was suppressed, but an attempt to invoke #{meth} was made"
|
75
|
+
end
|
76
|
+
|
77
|
+
def delete_parameter(key)
|
78
|
+
return if @keys_values.empty? || @params.nil?
|
79
|
+
|
80
|
+
@params.delete(key)
|
81
|
+
@argv.delete_if { |x| x == key or x.start_with?("#{key}=") }
|
82
|
+
@keys_values.delete(key)
|
83
|
+
|
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
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def page
|
92
|
+
@liquid_context.registers[:page]
|
93
|
+
end
|
94
|
+
|
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
|
101
|
+
|
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)
|
106
|
+
|
107
|
+
return if respond_to?(:no_arg_parsing) && no_arg_parsing
|
108
|
+
|
109
|
+
@params = @keys_values # TODO: @keys_values should be deleted
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,74 @@
|
|
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)
|
10
|
+
|
11
|
+
searcher = if Gem::Specification.respond_to?(:find)
|
12
|
+
Gem::Specification
|
13
|
+
elsif Gem.respond_to?(:searcher)
|
14
|
+
Gem.searcher.init_gemspecs
|
15
|
+
end
|
16
|
+
|
17
|
+
searcher&.find do |spec|
|
18
|
+
file.start_with? spec.full_gem_path
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def attribute
|
23
|
+
return unless @current_gem
|
24
|
+
|
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>
|
32
|
+
</div>
|
33
|
+
END_OUTPUT
|
34
|
+
end
|
35
|
+
|
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
|
44
|
+
|
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
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def annotate_globals
|
56
|
+
return unless @current_gem
|
57
|
+
|
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
|
64
|
+
|
65
|
+
def attribution_string
|
66
|
+
string = if @attribution == true
|
67
|
+
default_attribution
|
68
|
+
else
|
69
|
+
@attribution
|
70
|
+
end
|
71
|
+
String.interpolate { string }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'facets/string/camelcase'
|
2
|
+
require 'facets/string/snakecase'
|
3
|
+
require 'yaml'
|
4
|
+
|
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
|
15
|
+
|
16
|
+
if logger
|
17
|
+
logger.warn msg
|
18
|
+
else
|
19
|
+
puts msg.red
|
20
|
+
end
|
21
|
+
end
|
22
|
+
ENV.fetch(envar, nil)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
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.
|
38
|
+
|
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
|
48
|
+
|
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}
|
53
|
+
|
54
|
+
#{tag_config_msg}
|
55
|
+
END_MSG
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.register(klass, tag_name)
|
59
|
+
abort("Error: The #{tag_name} plugin does not define VERSION") \
|
60
|
+
unless klass.const_defined?(:VERSION)
|
61
|
+
|
62
|
+
version = klass.const_get(:VERSION)
|
63
|
+
|
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))
|
68
|
+
|
69
|
+
Liquid::Template.register_tag(tag_name, klass)
|
70
|
+
msg = generate_message(klass, tag_name, version)
|
71
|
+
PluginMetaLogger.instance.info { msg }
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.remove_html_tags(string)
|
75
|
+
string.gsub(/<[^>]*>/, '').strip
|
76
|
+
end
|
77
|
+
|
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
|
82
|
+
end
|
83
|
+
end
|
data/lib/{jekyll_plugin_support_class.rb → jekyll_plugin_support/jekyll_plugin_support_class.rb}
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative 'jekyll_custom_error'
|
1
|
+
require_relative '../error/jekyll_custom_error'
|
2
2
|
|
3
3
|
# Monkey patch StandardError so a new method called shorten_backtrace is added.
|
4
4
|
class StandardError
|
@@ -22,7 +22,7 @@ module JekyllSupport
|
|
22
22
|
|
23
23
|
# @return a new StandardError subclass containing the shorten_backtrace method
|
24
24
|
def define_error
|
25
|
-
Class.new
|
25
|
+
Class.new JekyllSupport::CustomError
|
26
26
|
end
|
27
27
|
module_function :define_error
|
28
28
|
|
@@ -1,8 +1,19 @@
|
|
1
1
|
require 'colorator'
|
2
2
|
require 'jekyll'
|
3
3
|
require 'jekyll_plugin_logger'
|
4
|
-
|
5
|
-
|
4
|
+
|
5
|
+
def require_directory(dir)
|
6
|
+
Dir[File.join(dir, '*.rb')].sort.each do |file|
|
7
|
+
require file unless file == __FILE__
|
8
|
+
end
|
9
|
+
end
|
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
|
6
17
|
|
7
18
|
module NoArgParsing
|
8
19
|
attr_accessor :no_arg_parsing
|
@@ -10,9 +21,10 @@ module NoArgParsing
|
|
10
21
|
@no_arg_parsing = true
|
11
22
|
end
|
12
23
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
24
|
+
require_directory __dir__
|
25
|
+
require_directory "#{__dir__}/block"
|
26
|
+
require_directory "#{__dir__}/error"
|
27
|
+
require_directory "#{__dir__}/generator"
|
28
|
+
require_directory "#{__dir__}/helper"
|
29
|
+
require_directory "#{__dir__}/jekyll_plugin_support"
|
30
|
+
require_directory "#{__dir__}/tag"
|
@@ -1,14 +1,11 @@
|
|
1
1
|
require 'pry'
|
2
|
-
require_relative 'jekyll_plugin_error_handling'
|
2
|
+
require_relative '../error/jekyll_plugin_error_handling'
|
3
3
|
|
4
4
|
module JekyllSupport
|
5
5
|
# Base class for Jekyll tags
|
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
|
@@ -1,12 +1,9 @@
|
|
1
|
-
require_relative 'jekyll_plugin_error_handling'
|
1
|
+
require_relative '../error/jekyll_plugin_error_handling'
|
2
2
|
|
3
3
|
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.0
|
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-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: facets
|
@@ -94,19 +94,20 @@ files:
|
|
94
94
|
- README.md
|
95
95
|
- Rakefile
|
96
96
|
- jekyll_plugin_support.gemspec
|
97
|
-
- lib/
|
98
|
-
- lib/
|
99
|
-
- lib/
|
100
|
-
- lib/
|
101
|
-
- lib/
|
97
|
+
- lib/block/jekyll_plugin_support_block.rb
|
98
|
+
- lib/block/jekyll_plugin_support_block_noarg.rb
|
99
|
+
- lib/error/jekyll_custom_error.rb
|
100
|
+
- lib/error/jekyll_plugin_error_handling.rb
|
101
|
+
- lib/generator/jekyll_plugin_support_generator.rb
|
102
|
+
- lib/helper/jekyll_plugin_helper.rb
|
103
|
+
- lib/helper/jekyll_plugin_helper_attribution.rb
|
104
|
+
- lib/helper/jekyll_plugin_helper_class.rb
|
102
105
|
- lib/jekyll_plugin_support.rb
|
106
|
+
- lib/jekyll_plugin_support/jekyll_plugin_support_class.rb
|
107
|
+
- lib/jekyll_plugin_support/jekyll_plugin_support_spec_support.rb
|
103
108
|
- lib/jekyll_plugin_support/version.rb
|
104
|
-
- lib/
|
105
|
-
- lib/
|
106
|
-
- lib/jekyll_plugin_support_class.rb
|
107
|
-
- lib/jekyll_plugin_support_spec_support.rb
|
108
|
-
- lib/jekyll_plugin_support_tag.rb
|
109
|
-
- lib/jekyll_plugin_support_tag_noarg.rb
|
109
|
+
- lib/tag/jekyll_plugin_support_tag.rb
|
110
|
+
- lib/tag/jekyll_plugin_support_tag_noarg.rb
|
110
111
|
- spec/custom_error_spec.rb
|
111
112
|
- spec/jekyll_plugin_helper_options_spec.rb
|
112
113
|
- spec/liquid_variable_parsing_spec.rb
|
@@ -139,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
140
|
- !ruby/object:Gem::Version
|
140
141
|
version: '0'
|
141
142
|
requirements: []
|
142
|
-
rubygems_version: 3.5.
|
143
|
+
rubygems_version: 3.5.16
|
143
144
|
signing_key:
|
144
145
|
specification_version: 4
|
145
146
|
summary: Provides a framework for writing and testing Jekyll plugins
|
data/lib/jekyll_plugin_helper.rb
DELETED
@@ -1,110 +0,0 @@
|
|
1
|
-
require 'facets/string/interpolate'
|
2
|
-
require 'key_value_parser'
|
3
|
-
require 'shellwords'
|
4
|
-
require_relative 'jekyll_plugin_helper_class'
|
5
|
-
require_relative 'jekyll_plugin_helper_attribution'
|
6
|
-
|
7
|
-
class JekyllPluginHelper
|
8
|
-
attr_accessor :liquid_context
|
9
|
-
attr_reader :argv, :attribution, :keys_values, :logger, :markup, :no_arg_parsing, :params, :tag_name,
|
10
|
-
:argv_original, :excerpt_caller, :keys_values_original, :params_original, :jpsh_subclass_caller
|
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 already know.
|
14
|
-
# @param argument_string [String] the arguments from 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, logger, no_arg_parsing)
|
22
|
-
@tag_name = tag_name
|
23
|
-
@logger = logger
|
24
|
-
@no_arg_parsing = no_arg_parsing
|
25
|
-
@markup = markup
|
26
|
-
rescue StandardError => e
|
27
|
-
e.shorten_backtrace
|
28
|
-
@logger.error { e.message }
|
29
|
-
end
|
30
|
-
|
31
|
-
# @return undefined if parameter was specified, removes it from the available tokens and returns value
|
32
|
-
def parameter_specified?(name, delete_param: true)
|
33
|
-
return false if @keys_values.to_s.empty?
|
34
|
-
|
35
|
-
key = name
|
36
|
-
key = name.to_sym if @keys_values&.first&.first.instance_of?(Symbol)
|
37
|
-
value = @keys_values[key]
|
38
|
-
delete_parameter(name) if delete_param
|
39
|
-
value
|
40
|
-
end
|
41
|
-
|
42
|
-
def reinitialize(markup)
|
43
|
-
# @keys_values was a Hash[Symbol, String|Boolean] but now it is Hash[String, String|Boolean]
|
44
|
-
@markup = markup
|
45
|
-
if @no_arg_parsing
|
46
|
-
define_singleton_method(:argv) { warn_fetch :argv }
|
47
|
-
define_singleton_method(:keys_values) { warn_fetch :keys_values }
|
48
|
-
define_singleton_method(:params) { warn_fetch :params }
|
49
|
-
define_singleton_method(:parameter_specified?) { |_name| warn_parse(:parameter_specified?) }
|
50
|
-
define_singleton_method(:delete_parameter) { |_name| warn_parse(:delete_parameter) }
|
51
|
-
@attribution = false
|
52
|
-
else
|
53
|
-
parse markup
|
54
|
-
@attribution = parameter_specified?('attribution') || false
|
55
|
-
@logger.debug { "@keys_values='#{@keys_values}'" }
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
# Call this method to return the remaining markup after `parameter_specified?` has been invoked.
|
60
|
-
def remaining_markup
|
61
|
-
@argv&.join(' ')
|
62
|
-
end
|
63
|
-
|
64
|
-
def remaining_markup_original
|
65
|
-
@argv_original&.join(' ')
|
66
|
-
end
|
67
|
-
|
68
|
-
def warn_fetch(variable)
|
69
|
-
abort "Error: Argument parsing was suppressed, but an attempt to obtain the value of #{variable} was made"
|
70
|
-
end
|
71
|
-
|
72
|
-
def warn_parse(meth)
|
73
|
-
abort "Error: Argument parsing was suppressed, but an attempt to invoke #{meth} was made"
|
74
|
-
end
|
75
|
-
|
76
|
-
def delete_parameter(key)
|
77
|
-
return if @keys_values.empty? || @params.nil?
|
78
|
-
|
79
|
-
@params.delete(key)
|
80
|
-
@argv.delete_if { |x| x == key or x.start_with?("#{key}=") }
|
81
|
-
@keys_values.delete(key)
|
82
|
-
|
83
|
-
@params_original.delete(key)
|
84
|
-
@argv_original.delete_if { |x| x == key or x.start_with?("#{key}=") }
|
85
|
-
@keys_values_original.delete(key)
|
86
|
-
end
|
87
|
-
|
88
|
-
private
|
89
|
-
|
90
|
-
def page
|
91
|
-
@liquid_context.registers[:page]
|
92
|
-
end
|
93
|
-
|
94
|
-
def parse(markup)
|
95
|
-
@argv_original = Shellwords.split(markup)
|
96
|
-
@keys_values_original = KeyValueParser
|
97
|
-
.new({}, { array_values: false, normalize_keys: false, separator: /=/ })
|
98
|
-
.parse(@argv_original)
|
99
|
-
@params_original = @keys_values_original unless respond_to?(:no_arg_parsing) && no_arg_parsing
|
100
|
-
|
101
|
-
@argv = Shellwords.split(self.class.expand_env(markup, logger))
|
102
|
-
@keys_values = KeyValueParser
|
103
|
-
.new({}, { array_values: false, normalize_keys: false, separator: /=/ })
|
104
|
-
.parse(@argv)
|
105
|
-
|
106
|
-
return if respond_to?(:no_arg_parsing) && no_arg_parsing
|
107
|
-
|
108
|
-
@params = @keys_values # TODO: @keys_values should be deleted
|
109
|
-
end
|
110
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
# Attribution aspect of JekyllPluginHelper
|
2
|
-
class JekyllPluginHelper
|
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
|
-
# See https://stackoverflow.com/a/75890279/553865
|
6
|
-
def self.current_spec(file)
|
7
|
-
abort 'JekyllPluginHelper::current_spec: file is nil' if file.nil?
|
8
|
-
return nil unless File.exist?(file)
|
9
|
-
|
10
|
-
searcher = if Gem::Specification.respond_to?(:find)
|
11
|
-
Gem::Specification
|
12
|
-
elsif Gem.respond_to?(:searcher)
|
13
|
-
Gem.searcher.init_gemspecs
|
14
|
-
end
|
15
|
-
|
16
|
-
searcher&.find do |spec|
|
17
|
-
file.start_with? spec.full_gem_path
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def attribute
|
22
|
-
return unless @current_gem
|
23
|
-
|
24
|
-
<<~END_OUTPUT
|
25
|
-
<div id="jps_attribute_#{rand(999_999)}" class="jps_attribute">
|
26
|
-
<div>
|
27
|
-
<a href="#{@homepage}" target="_blank" rel="nofollow">
|
28
|
-
#{attribution_string}
|
29
|
-
</a>
|
30
|
-
</div>
|
31
|
-
</div>
|
32
|
-
END_OUTPUT
|
33
|
-
end
|
34
|
-
|
35
|
-
def default_attribution
|
36
|
-
authors = @authors&.join(', ')
|
37
|
-
result = "Generated by the \#{@name} v\#{@version} Jekyll plugin"
|
38
|
-
result << ", written by #{authors}" if authors
|
39
|
-
result << " \#{@published_date}" if @published_date
|
40
|
-
result << '.'
|
41
|
-
result
|
42
|
-
end
|
43
|
-
|
44
|
-
# Sets @current_gem if file points at a uniquely named file within a gem.
|
45
|
-
# @param file must be a fully qualified file name in a gem, for example: __FILE__
|
46
|
-
def gem_file(file)
|
47
|
-
@current_gem = JekyllPluginHelper.current_spec file
|
48
|
-
@logger.debug "No gem found for '#{file} was found." unless @current_gem
|
49
|
-
annotate_globals if @attribution && @current_gem
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
def annotate_globals
|
55
|
-
return unless @current_gem
|
56
|
-
|
57
|
-
@name = @current_gem.name
|
58
|
-
@authors = @current_gem.authors
|
59
|
-
@homepage = @current_gem.homepage
|
60
|
-
@published_date = @current_gem.date.to_date.to_s
|
61
|
-
@version = @current_gem.version
|
62
|
-
end
|
63
|
-
|
64
|
-
def attribution_string
|
65
|
-
string = if @attribution == true
|
66
|
-
default_attribution
|
67
|
-
else
|
68
|
-
@attribution
|
69
|
-
end
|
70
|
-
String.interpolate { string }
|
71
|
-
end
|
72
|
-
end
|
@@ -1,81 +0,0 @@
|
|
1
|
-
require 'facets/string/camelcase'
|
2
|
-
require 'facets/string/snakecase'
|
3
|
-
require 'yaml'
|
4
|
-
|
5
|
-
# Class methods for JekyllPluginHelper
|
6
|
-
class JekyllPluginHelper
|
7
|
-
# Expand an environment variable reference
|
8
|
-
def self.expand_env(str, logger = nil, die_if_undefined: false)
|
9
|
-
str&.gsub(/\$([a-zA-Z_][a-zA-Z0-9_]*)|\${\g<1>}/) do
|
10
|
-
envar = Regexp.last_match(1)
|
11
|
-
unless ENV.key? envar
|
12
|
-
msg = "jekyll_plugin_support error: environment variable #{envar} is undefined"
|
13
|
-
raise JekyllPluginSupportError, msg.red, [] if die_if_undefined
|
14
|
-
|
15
|
-
if logger
|
16
|
-
logger.warn msg
|
17
|
-
else
|
18
|
-
puts msg.red
|
19
|
-
end
|
20
|
-
end
|
21
|
-
ENV.fetch(envar, nil)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.generate_message(klass, tag_name, version)
|
26
|
-
error_name_stub = klass.name.include?('::') ? klass.name.split('::')[1] : klass.name
|
27
|
-
error_ruby_class_name = "#{error_name_stub.camelcase(:upper)}Error"
|
28
|
-
config_die_key = "die_on_#{error_ruby_class_name.snakecase}"
|
29
|
-
error_css_class_name = error_ruby_class_name.split('::').last.snakecase
|
30
|
-
config = YAML.load_file('_config.yml')
|
31
|
-
tag_config = config[tag_name]
|
32
|
-
tag_config_msg = if tag_config.nil?
|
33
|
-
<<~END_MSG
|
34
|
-
_config.yml does not contain configuration information for this plugin.
|
35
|
-
You could add a section containing default values by specifying a section for the tag name,
|
36
|
-
and an entry whose name starts with `die_on_`, followed by a snake_case version of the error name.
|
37
|
-
|
38
|
-
#{tag_name}:
|
39
|
-
#{config_die_key}: false
|
40
|
-
END_MSG
|
41
|
-
else
|
42
|
-
<<~END_MSG
|
43
|
-
_config.yml contains the following configuration for this plugin:
|
44
|
-
#{tag_config}
|
45
|
-
END_MSG
|
46
|
-
end
|
47
|
-
|
48
|
-
<<~END_MSG
|
49
|
-
Loaded plugin #{tag_name} v#{version}. It has:
|
50
|
-
Error class: #{error_ruby_class_name}
|
51
|
-
CSS class for error messages: #{error_css_class_name}
|
52
|
-
|
53
|
-
#{tag_config_msg}
|
54
|
-
END_MSG
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.register(klass, tag_name)
|
58
|
-
abort("Error: The #{tag_name} plugin does not define VERSION") \
|
59
|
-
unless klass.const_defined?(:VERSION)
|
60
|
-
|
61
|
-
version = klass.const_get(:VERSION)
|
62
|
-
|
63
|
-
abort("Error: The #{tag_name} plugin is not an instance of JekyllSupport::JekyllBlock or JekyllSupport::JekyllTag") \
|
64
|
-
unless klass.instance_of?(Class) &&
|
65
|
-
(klass.ancestors.include?(JekyllSupport::JekyllBlock) ||
|
66
|
-
klass.ancestors.include?(JekyllSupport::JekyllTag))
|
67
|
-
|
68
|
-
Liquid::Template.register_tag(tag_name, klass)
|
69
|
-
msg = generate_message(klass, tag_name, version)
|
70
|
-
PluginMetaLogger.instance.info { msg }
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.remove_html_tags(string)
|
74
|
-
string.gsub(/<[^>]*>/, '').strip
|
75
|
-
end
|
76
|
-
|
77
|
-
# strip leading and trailing quotes if present
|
78
|
-
def self.remove_quotes(string)
|
79
|
-
string.strip.gsub(/\A'|\A"|'\Z|"\Z/, '').strip if string
|
80
|
-
end
|
81
|
-
end
|
File without changes
|