jekyll_pre 1.1.1 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b79b7abf9ee4c8a48c3886fbc286e7f15c3525cd6e4df1aa48afaa57b2912d70
4
- data.tar.gz: 20e448f4ecc75578c46728c821bc09529e587758cfcc0b40783ee6fd487ee095
3
+ metadata.gz: be2fcd1765446ab64973e355acb073057dea3c98ed1be553362b5b755e5453fb
4
+ data.tar.gz: 33b14de234b5764673af3c9380d6ae32fa5a429294f7ee5f53d094aa63bf1f87
5
5
  SHA512:
6
- metadata.gz: 29643f46fdfed357b6ec9fcecc7344a5da043ddebc7fcd1f9f4d09d6d249b5f43c81f8d83e6b627879c2bbb1f67f40e7fe246f6451b8b7df672c4f3d30551df0
7
- data.tar.gz: 2baae24a428b940bff90b8871a84b6c0c13af534af066755ff0308e22534c74d75435f056e873d9fd135e7902b645ba5df49c4b4b8e3f82b0afcbc8e9031b036
6
+ metadata.gz: 46fcc4e0dcab10f27bfc9f8fa408e84e5d5c3c19f926d1de51167b39754740a2a4a3af2a17ca4c4f8dc2bf25011283205137c7afa9d144abb67ee6c2479276a5
7
+ data.tar.gz: c39c5e30e3386d1eeb3029d7cf31ab159fcb8b32fb3b72fa5f03d5af8269daa30b7cf308e0bdbf1905180a468f88b2e7b00ab1e440daf75ba5ee96987bc1a727
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## 1.1.4
2
+ * Added `highlight` regex option
3
+ * Now using `lib/jekyll_tag_helper.rb` to parse markup
4
+
5
+ ## 1.1.3
6
+ * Documented the `data-lt-active="false"` attribute.
7
+ * Added the `dark` option, and [provided CSS](https://www.mslinn.com/blog/2020/10/03/jekyll-plugins.html#pre_css).
8
+
9
+ ## 1.1.2 / 2022-04-05
10
+ * Updated to `jekyll_plugin_logger` v2.1.0
11
+
1
12
  ## 1.1.1 / 2022-03-31
2
13
  * Added `numbered_line` CSS class for unselectable line numbers
3
14
 
data/README.md CHANGED
@@ -10,6 +10,7 @@ This Jekyll plugin provides 2 new Liquid tags that work together:
10
10
  Contents of pre tag
11
11
  {% endpre %}
12
12
  ```
13
+ The generated <pre></pre> tag has an `data-lt-active="false"` attribute, so [LanguageTool](https://forum.languagetool.org/t/avoid-spell-check-on-certain-html-inputs-manually/3944) does not check the spelling or grammar of the contents.
13
14
  * A `noselect` tag that can renders HTML content passed to it unselectable.
14
15
  ```
15
16
  {% pre [copyButton] %}
@@ -39,7 +40,7 @@ Below are the CSS declarations that I defined pertaining to the pre and noselect
39
40
  ```
40
41
 
41
42
  ## Additional Information
42
- More information is available on my web site about [my Jekyll plugins](https://www.mslinn.com/blog/2020/10/03/jekyll-plugins.html).
43
+ More information is available on [my web site](https://www.mslinn.com/blog/2020/10/03/jekyll-plugins.html#jekyll_pre).
43
44
 
44
45
 
45
46
  ## Installation
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JekyllPreVersion
4
- VERSION = "1.1.1"
4
+ VERSION = "1.1.4"
5
5
  end
data/lib/jekyll_pre.rb CHANGED
@@ -2,7 +2,10 @@
2
2
 
3
3
  require "liquid"
4
4
  require "jekyll_plugin_logger"
5
+ require 'key_value_parser'
6
+ require "shellwords"
5
7
  require_relative "jekyll_pre/version"
8
+ require_relative "jekyll_tag_helper"
6
9
 
7
10
  module JekyllPluginPreName
8
11
  PLUGIN_NAME = "jekyll_pre"
@@ -33,22 +36,28 @@ class PreTagBlock < Liquid::Block
33
36
  @@suffix = " title='Copy to clipboard'><img src='/assets/images/clippy.svg' " \
34
37
  "alt='Copy to clipboard' style='width: 13px'></button>"
35
38
 
39
+ def self.highlight(content, pattern)
40
+ content.gsub(Regexp::new(pattern), "<span class='bg_yellow'>\\0</span>")
41
+ end
42
+
36
43
  def self.make_copy_button(pre_id)
37
44
  "#{@@prefix}'##{pre_id}'#{@@suffix}"
38
45
  end
39
46
 
40
- def self.make_pre(make_copy_button, number_lines, label, content)
47
+ def self.make_pre(make_copy_button, number_lines, label, dark, highlight_pattern, content) # rubocop:disable Metrics/ParameterLists
48
+ dark_label = " darkLabel" if dark
41
49
  label = if label.to_s.empty?
42
50
  ""
43
51
  elsif label.to_s.downcase.strip == "shell"
44
- "<div class='codeLabel unselectable' data-lt-active='false'>Shell</div>"
52
+ "<div class='codeLabel unselectable#{dark_label}' data-lt-active='false'>Shell</div>"
45
53
  else
46
- "<div class='codeLabel unselectable' data-lt-active='false'>#{label}</div>"
54
+ "<div class='codeLabel unselectable#{dark_label}' data-lt-active='false'>#{label}</div>"
47
55
  end
48
56
  pre_id = "id#{SecureRandom.hex(6)}"
49
57
  copy_button = make_copy_button ? PreTagBlock.make_copy_button(pre_id) : ""
58
+ content = PreTagBlock.highlight(content, highlight_pattern) if highlight_pattern
50
59
  content = PreTagBlock.number_content(content) if number_lines
51
- "#{label}<pre data-lt-active='false' class='maxOneScreenHigh copyContainer' id='#{pre_id}'>#{copy_button}#{content.strip}</pre>"
60
+ "#{label}<pre data-lt-active='false' class='maxOneScreenHigh copyContainer#{dark}' id='#{pre_id}'>#{copy_button}#{content.strip}</pre>"
52
61
  end
53
62
 
54
63
  def self.number_content(content)
@@ -66,33 +75,40 @@ class PreTagBlock < Liquid::Block
66
75
  end
67
76
 
68
77
  # @param _tag_name [String] is the name of the tag, which we already know.
69
- # @param argument_string [String] the arguments from the web page.
78
+ # @param markup [String] the arguments from the web page.
70
79
  # @param _tokens [Liquid::ParseContext] tokenized command line
80
+ # By default it has two keys: :locale and :line_numbers, the first is a Liquid::I18n object, and the second,
81
+ # a boolean parameter that determines if error messages should display the line number the error occurred.
82
+ # This argument is used mostly to display localized error messages on Liquid built-in Tags and Filters.
83
+ # See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
71
84
  # @return [void]
72
- def initialize(_tag_name, argument_string, _tokens)
85
+ def initialize(_tag_name, markup, _tokens)
73
86
  super
74
- argument_string = "" if argument_string.nil?
75
- argument_string.strip!
76
-
77
- @logger = PluginMetaLogger.instance.new_logger(self)
78
-
79
- @make_copy_button = argument_string.include? "copyButton"
80
- remaining_text = argument_string.sub("copyButton", "").strip
87
+ markup = "" if markup.nil?
88
+ markup.strip!
81
89
 
82
- @number_lines = remaining_text.include? "number"
83
- remaining_text = remaining_text.sub("number", "").strip
84
-
85
- @label = remaining_text
86
-
87
- @logger.debug { "@make_copy_button = '#{@make_copy_button}'; argument_string = '#{argument_string}'; remaining_text = '#{remaining_text}'" }
90
+ @logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
91
+ @helper = JekyllTagHelper.new(tag_name, markup, @logger)
88
92
  end
89
93
 
90
94
  # Method prescribed by the Jekyll plugin lifecycle.
95
+ # @param liquid_context [Liquid::Context]
91
96
  # @return [String]
92
- def render(context)
97
+ def render(liquid_context)
93
98
  content = super
99
+ @helper.liquid_context = liquid_context
100
+
101
+ @highlight = @helper.parameter_specified? "highlight"
102
+ @make_copy_button = @helper.parameter_specified? "copyButton"
103
+ @number_lines = @helper.parameter_specified? "number"
104
+ @dark = " dark" if @helper.parameter_specified? "dark"
105
+ @label = @helper.parameter_specified? "label"
106
+
107
+ # If a label was specified, use it, otherwise concatenate any dangling parameters and use that as the label
108
+ @label ||= @helper.params.join(" ")
109
+
94
110
  @logger.debug { "@make_copy_button = '#{@make_copy_button}'; @label = '#{@label}'" }
95
- PreTagBlock.make_pre(@make_copy_button, @number_lines, @label, content)
111
+ PreTagBlock.make_pre(@make_copy_button, @number_lines, @label, @dark, @highlight, content)
96
112
  end
97
113
  end
98
114
 
@@ -100,20 +116,20 @@ end
100
116
  # Also, space before the closing percent is signficant %}"""
101
117
  class UnselectableTag < Liquid::Tag
102
118
  # @param _tag_name [String] is the name of the tag, which we already know.
103
- # @param argument_string [String] the arguments from the web page.
119
+ # @param markup [String] the arguments from the web page.
104
120
  # @param _tokens [Liquid::ParseContext] tokenized command line
105
121
  # @return [void]
106
- def initialize(_tag_name, argument_string, _tokens)
122
+ def initialize(_tag_name, markup, _tokens)
107
123
  super
108
124
  @logger = PluginMetaLogger.instance.new_logger(self)
109
125
 
110
- @argument_string = argument_string
111
- @argument_string = "$ " if @argument_string.nil? || @argument_string.empty?
112
- @logger.debug { "UnselectableTag: argument_string= '#{@argument_string}'" }
126
+ @markup = markup
127
+ @markup = "$ " if @markup.nil? || @markup.empty?
128
+ @logger.debug { "UnselectableTag: markup= '#{@markup}'" }
113
129
  end
114
130
 
115
131
  def render(_)
116
- "<span class='unselectable'>#{@argument_string}</span>"
132
+ "<span class='unselectable'>#{@markup}</span>"
117
133
  end
118
134
  end
119
135
 
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "shellwords"
4
+ require 'key_value_parser'
5
+
6
+ class JekyllTagHelper
7
+ attr_reader :argv, :liquid_context, :logger, :params, :tag_name
8
+
9
+ def self.escape_html(string)
10
+ string.gsub("&", "&amp;")
11
+ .gsub("{", "&#123;")
12
+ .gsub("}", "&#125;")
13
+ .gsub("<", "&lt;")
14
+ end
15
+
16
+ # Expand a environment variable reference
17
+ def self.expand_env(str, die_if_undefined=false)
18
+ str.gsub(/\$([a-zA-Z_][a-zA-Z0-9_]*)|\${\g<1>}|%\g<1>%/) do
19
+ envar = Regexp.last_match(1)
20
+ raise FlexibleError, "flexible_include error: #{envar} is undefined".red, [] if !ENV.key?(envar) && die_if_undefined # Suppress stack trace
21
+ ENV[envar]
22
+ end
23
+ end
24
+
25
+ # strip leading and trailing quotes if present
26
+ def self.remove_quotes(string)
27
+ string.strip.gsub(/\A'|\A"|'\Z|"\Z/, '').strip if string
28
+ end
29
+
30
+ def initialize(tag_name, markup, logger)
31
+ @tag_name = tag_name
32
+ @argv = Shellwords.split(markup)
33
+ @keys_values = KeyValueParser.new.parse(@argv) # Hash[Symbol, String|Boolean]
34
+ @logger = logger
35
+ @logger.debug { "@keys_values='#{@keys_values}'" }
36
+ end
37
+
38
+ def delete_parameter(name)
39
+ @params.delete(name)
40
+ @argv.delete_if { |x| x.start_with? name }
41
+ @keys_values.delete(name.to_sym)
42
+ end
43
+
44
+ # @return if parameter was specified, returns value and removes it from the available tokens
45
+ def parameter_specified?(name)
46
+ value = @keys_values[name.to_sym]
47
+ delete_parameter(name)
48
+ value
49
+ end
50
+
51
+ PREDEFINED_SCOPE_KEYS = [:include, :page].freeze
52
+
53
+ # Finds variables defined in an invoking include, or maybe somewhere else
54
+ # @return variable value or nil
55
+ def dereference_include_variable(name)
56
+ @liquid_context.scopes.each do |scope|
57
+ next if PREDEFINED_SCOPE_KEYS.include? scope.keys.first
58
+
59
+ value = scope[name]
60
+ return value if value
61
+ end
62
+ nil
63
+ end
64
+
65
+ # @return value of variable, or the empty string
66
+ def dereference_variable(name)
67
+ value = @liquid_context[name] # Finds variables named like 'include.my_variable', found in @liquid_context.scopes.first
68
+ value ||= @page[name] if @page # Finds variables named like 'page.my_variable'
69
+ value ||= dereference_include_variable(name)
70
+ value ||= ""
71
+ value
72
+ end
73
+
74
+ # Sets @params by replacing any Liquid variable names with their values
75
+ def liquid_context=(context)
76
+ @liquid_context = context
77
+ @params = @keys_values.map { |k, _v| lookup_variable(k) }
78
+ end
79
+
80
+ def lookup_variable(symbol)
81
+ string = symbol.to_s
82
+ return string unless string.start_with?("{{") && string.end_with?("}}")
83
+
84
+ dereference_variable(string.delete_prefix("{{").delete_suffix("}}"))
85
+ end
86
+
87
+ def page
88
+ @liquid_context.registers[:page]
89
+ end
90
+ end
data/spec/pre_spec.rb CHANGED
@@ -45,4 +45,21 @@ RSpec.describe(PreTagBlock) do
45
45
  END_CONTENT
46
46
  expect(numbered_content).to eq(expected_content)
47
47
  end
48
+
49
+ it "highlights regex patterns" do
50
+ content = <<~END_CONTENT
51
+ Line 1
52
+ Line 2
53
+ Line 3
54
+ Line 4
55
+ Line 5
56
+ Line 6
57
+ Line 7
58
+ Line 8
59
+ Line 9
60
+ Line 10
61
+ END_CONTENT
62
+ highlighted = PreTagBlock.highlight(content, ".*2").split("\n")[1]
63
+ expect(highlighted).to eq("<span class='bg_yellow'> Line 2</span>")
64
+ end
48
65
  end
@@ -1,4 +1,5 @@
1
1
  example_id | status | run_time |
2
2
  ----------------------- | ------ | --------------- |
3
- ./spec/pre_spec.rb[1:1] | passed | 0.00366 seconds |
4
- ./spec/pre_spec.rb[1:2] | passed | 0.00288 seconds |
3
+ ./spec/pre_spec.rb[1:1] | passed | 0.00187 seconds |
4
+ ./spec/pre_spec.rb[1:2] | passed | 0.00285 seconds |
5
+ ./spec/pre_spec.rb[1:3] | passed | 0.00056 seconds |
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll_pre
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Slinn
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-31 00:00:00.000000000 Z
11
+ date: 2022-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -112,6 +112,7 @@ files:
112
112
  - jekyll_pre.gemspec
113
113
  - lib/jekyll_pre.rb
114
114
  - lib/jekyll_pre/version.rb
115
+ - lib/jekyll_tag_helper.rb
115
116
  - spec/pre_spec.rb
116
117
  - spec/spec_helper.rb
117
118
  - spec/status_persistence.txt