jekyll_pre 1.1.1 → 1.1.4

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 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