jekyll_pre 1.1.2 → 1.1.5

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: '02751991aafe0decd461b0596ea3b8e06cd537bfe036ed5d2d5851aebf7c1295'
4
- data.tar.gz: b2f326314d48b1752ad40b9c50c4df9c7f39dfb93d80662dddc9bab2ebe7291d
3
+ metadata.gz: a3eced8ae5430c67a303f08c90a38caf16c46efbad4e11232aa95ed9580c2f98
4
+ data.tar.gz: 9370b4fab76dc5ba5487c0d0876907ed9366d0f1e777e63ca8250121a9a32533
5
5
  SHA512:
6
- metadata.gz: 8f62ab9616720b33cd9598c431501e1ac4de30ed8c0fd9a8afaba076f8f4dde15b8885381f4d2716f48c32b68a0dbda6fd021e1f3d0806a46a28322c4ab34671
7
- data.tar.gz: d28408a99c9a4e465caedb7a71296c6ecdeb5a4e13719e2360039fc8eeb84d378034cd996162dbbc3fae57840b1da5afc4972fc892787161d291ff9dbc06f835
6
+ metadata.gz: 7fc327f37d0c5dc7f54ba78837984a05603ae24bbdee5e888eebdb01bc8d377ecd08bbc4b18a68c97a9bd3f1272f359cb8da53ee7a2143938793d5dca298fb31
7
+ data.tar.gz: 656acb136598d957e9b129a2ebd71cfb905f63191c6c0c09eb0565c9070c71d5790b1319289b6ac70d71f15b8710a1af5e693240102f10f5c4ecce0068784252
data/.rubocop.yml CHANGED
@@ -1,6 +1,6 @@
1
- require: rubocop-jekyll
2
- inherit_gem:
3
- rubocop-jekyll: .rubocop.yml
1
+ # require: rubocop-jekyll
2
+ # inherit_gem:
3
+ # rubocop-jekyll: .rubocop.yml
4
4
 
5
5
  AllCops:
6
6
  Exclude:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## 1.1.5
2
+ * Added `class` and `style` options to allow for specifying additional CSS classes and inline CSS
3
+ * Added `clear` option to ensure no images overlap the pre output
4
+
5
+ ## 1.1.4
6
+ * Added `highlight` regex option
7
+ * Now using `lib/jekyll_tag_helper.rb` to parse markup
8
+
9
+ ## 1.1.3
10
+ * Documented the `data-lt-active="false"` attribute.
11
+ * Added the `dark` option, and [provided CSS](https://www.mslinn.com/blog/2020/10/03/jekyll-plugins.html#pre_css).
12
+
1
13
  ## 1.1.2 / 2022-04-05
2
14
  * Updated to `jekyll_plugin_logger` v2.1.0
3
15
 
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
data/jekyll_pre.gemspec CHANGED
@@ -39,10 +39,10 @@ Gem::Specification.new do |spec|
39
39
  spec.add_dependency "key-value-parser"
40
40
  spec.add_dependency "shellwords"
41
41
 
42
- spec.add_development_dependency "debase"
42
+ # spec.add_development_dependency "debase"
43
43
  # spec.add_development_dependency "rubocop-jekyll"
44
44
  # spec.add_development_dependency "rubocop-rake"
45
45
  # spec.add_development_dependency "rubocop-rspec"
46
- spec.add_development_dependency "ruby-debug-ide"
46
+ # spec.add_development_dependency "ruby-debug-ide"
47
47
  end
48
48
  # rubocop:enable Metrics/BlockLength
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JekyllPreVersion
4
- VERSION = "1.1.2"
4
+ VERSION = "1.1.5"
5
5
  end
data/lib/jekyll_pre.rb CHANGED
@@ -1,11 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "liquid"
4
- require "jekyll_plugin_logger"
5
- require_relative "jekyll_pre/version"
3
+ require 'liquid'
4
+ require 'jekyll_plugin_logger'
5
+ require 'key_value_parser'
6
+ require 'shellwords'
7
+ require_relative 'jekyll_pre/version'
8
+ require_relative 'jekyll_tag_helper'
6
9
 
7
10
  module JekyllPluginPreName
8
- PLUGIN_NAME = "jekyll_pre"
11
+ PLUGIN_NAME = 'jekyll_pre'
9
12
  end
10
13
 
11
14
  # """
@@ -33,31 +36,47 @@ 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, css_class, style, clear, content) # rubocop:disable Metrics/ParameterLists, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
48
+ pre_clear = label_clear = ''
49
+ if clear
50
+ if label.to_s.empty?
51
+ pre_clear = ' clear'
52
+ else
53
+ label_clear = ' clear'
54
+ end
55
+ end
56
+ css_class = css_class ? " #{css_class}" : ''
57
+ style = style ? " style='#{style}'" : ''
58
+ dark_label = ' darkLabel' if dark
41
59
  label = if label.to_s.empty?
42
- ""
43
- elsif label.to_s.downcase.strip == "shell"
44
- "<div class='codeLabel unselectable' data-lt-active='false'>Shell</div>"
60
+ ''
61
+ elsif label.to_s.downcase.strip == 'shell'
62
+ "<div class='codeLabel unselectable#{dark_label}#{label_clear}' data-lt-active='false'>Shell</div>"
45
63
  else
46
- "<div class='codeLabel unselectable' data-lt-active='false'>#{label}</div>"
64
+ "<div class='codeLabel unselectable#{dark_label}#{label_clear}' data-lt-active='false'>#{label}</div>"
47
65
  end
48
66
  pre_id = "id#{SecureRandom.hex(6)}"
49
- copy_button = make_copy_button ? PreTagBlock.make_copy_button(pre_id) : ""
67
+ copy_button = make_copy_button ? PreTagBlock.make_copy_button(pre_id) : ''
68
+ content = PreTagBlock.highlight(content, highlight_pattern) if highlight_pattern
50
69
  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>"
70
+ "#{label}<pre data-lt-active='false' class='maxOneScreenHigh copyContainer#{dark}#{pre_clear}#{css_class}'#{style} id='#{pre_id}'>#{copy_button}#{content.strip}</pre>"
52
71
  end
53
72
 
54
- def self.number_content(content)
73
+ def self.number_content(content) # rubocop:disable Metrics/MethodLength
55
74
  lines = content.split("\n")
56
75
  digits = lines.length.to_s.length
57
76
  i = 0
58
77
  numbered_content = lines.map do |line|
59
78
  i += 1
60
- number = i.to_s.rjust(digits, " ")
79
+ number = i.to_s.rjust(digits, ' ')
61
80
  "<span class='unselectable numbered_line'> #{number}: </span>#{line}"
62
81
  end
63
82
  result = numbered_content.join("\n")
@@ -66,33 +85,43 @@ class PreTagBlock < Liquid::Block
66
85
  end
67
86
 
68
87
  # @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.
88
+ # @param markup [String] the arguments from the web page.
70
89
  # @param _tokens [Liquid::ParseContext] tokenized command line
90
+ # By default it has two keys: :locale and :line_numbers, the first is a Liquid::I18n object, and the second,
91
+ # a boolean parameter that determines if error messages should display the line number the error occurred.
92
+ # This argument is used mostly to display localized error messages on Liquid built-in Tags and Filters.
93
+ # See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
71
94
  # @return [void]
72
- def initialize(_tag_name, argument_string, _tokens)
95
+ def initialize(_tag_name, markup, _tokens)
73
96
  super
74
- argument_string = "" if argument_string.nil?
75
- argument_string.strip!
97
+ markup = '' if markup.nil?
98
+ markup.strip!
76
99
 
77
100
  @logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
78
-
79
- @make_copy_button = argument_string.include? "copyButton"
80
- remaining_text = argument_string.sub("copyButton", "").strip
81
-
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}'" }
101
+ @helper = JekyllTagHelper.new(tag_name, markup, @logger)
88
102
  end
89
103
 
90
104
  # Method prescribed by the Jekyll plugin lifecycle.
105
+ # @param liquid_context [Liquid::Context]
91
106
  # @return [String]
92
- def render(context)
107
+ def render(liquid_context) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
93
108
  content = super
109
+ @helper.liquid_context = liquid_context
110
+
111
+ @clear = @helper.parameter_specified?('clear')
112
+ @class = @helper.parameter_specified?('class')
113
+ @highlight = @helper.parameter_specified? 'highlight'
114
+ @make_copy_button = @helper.parameter_specified? 'copyButton'
115
+ @number_lines = @helper.parameter_specified? 'number'
116
+ @dark = ' dark' if @helper.parameter_specified? 'dark'
117
+ @label = @helper.parameter_specified? 'label'
118
+ @style = @helper.parameter_specified?('style')
119
+
120
+ # If a label was specified, use it, otherwise concatenate any dangling parameters and use that as the label
121
+ @label ||= @helper.params.join(' ')
122
+
94
123
  @logger.debug { "@make_copy_button = '#{@make_copy_button}'; @label = '#{@label}'" }
95
- PreTagBlock.make_pre(@make_copy_button, @number_lines, @label, content)
124
+ PreTagBlock.make_pre(@make_copy_button, @number_lines, @label, @dark, @highlight, @class, @style, @clear, content)
96
125
  end
97
126
  end
98
127
 
@@ -100,23 +129,23 @@ end
100
129
  # Also, space before the closing percent is signficant %}"""
101
130
  class UnselectableTag < Liquid::Tag
102
131
  # @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.
132
+ # @param markup [String] the arguments from the web page.
104
133
  # @param _tokens [Liquid::ParseContext] tokenized command line
105
134
  # @return [void]
106
- def initialize(_tag_name, argument_string, _tokens)
135
+ def initialize(_tag_name, markup, _tokens)
107
136
  super
108
137
  @logger = PluginMetaLogger.instance.new_logger(self)
109
138
 
110
- @argument_string = argument_string
111
- @argument_string = "$ " if @argument_string.nil? || @argument_string.empty?
112
- @logger.debug { "UnselectableTag: argument_string= '#{@argument_string}'" }
139
+ @markup = markup
140
+ @markup = '$ ' if @markup.nil? || @markup.empty?
141
+ @logger.debug { "UnselectableTag: markup= '#{@markup}'" }
113
142
  end
114
143
 
115
144
  def render(_)
116
- "<span class='unselectable'>#{@argument_string}</span>"
145
+ "<span class='unselectable'>#{@markup}</span>"
117
146
  end
118
147
  end
119
148
 
120
149
  PluginMetaLogger.instance.info { "Loaded #{JekyllPluginPreName::PLUGIN_NAME} v#{JekyllPreVersion::VERSION} plugin." }
121
- Liquid::Template.register_tag("pre", PreTagBlock)
122
- Liquid::Template.register_tag("noselect", UnselectableTag)
150
+ Liquid::Template.register_tag('pre', PreTagBlock)
151
+ Liquid::Template.register_tag('noselect', UnselectableTag)
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'shellwords'
4
+ require 'key_value_parser'
5
+
6
+ # Parses arguments and options
7
+ class JekyllTagHelper
8
+ attr_reader :argv, :liquid_context, :logger, :params, :tag_name
9
+
10
+ def self.escape_html(string)
11
+ string.gsub('&', '&amp;')
12
+ .gsub('{', '&#123;')
13
+ .gsub('}', '&#125;')
14
+ .gsub('<', '&lt;')
15
+ end
16
+
17
+ # Expand a environment variable reference
18
+ def self.expand_env(str, die_if_undefined: false)
19
+ str.gsub(/\$([a-zA-Z_][a-zA-Z0-9_]*)|\${\g<1>}|%\g<1>%/) do
20
+ envar = Regexp.last_match(1)
21
+ raise FlexibleError, "flexible_include error: #{envar} is undefined".red, [] if !ENV.key?(envar) && die_if_undefined # Suppress stack trace
22
+
23
+ ENV[envar]
24
+ end
25
+ end
26
+
27
+ # strip leading and trailing quotes if present
28
+ def self.remove_quotes(string)
29
+ string.strip.gsub(/\A'|\A"|'\Z|"\Z/, '').strip if string
30
+ end
31
+
32
+ def initialize(tag_name, markup, logger)
33
+ @tag_name = tag_name
34
+ @argv = Shellwords.split(markup)
35
+ @keys_values = KeyValueParser.new.parse(@argv) # Hash[Symbol, String|Boolean]
36
+ @logger = logger
37
+ @logger.debug { "@keys_values='#{@keys_values}'" }
38
+ end
39
+
40
+ def delete_parameter(name)
41
+ @params.delete(name)
42
+ @argv.delete_if { |x| x.start_with? name }
43
+ @keys_values.delete(name.to_sym)
44
+ end
45
+
46
+ # @return if parameter was specified, returns value and removes it from the available tokens
47
+ def parameter_specified?(name)
48
+ value = @keys_values[name.to_sym]
49
+ delete_parameter(name)
50
+ value
51
+ end
52
+
53
+ PREDEFINED_SCOPE_KEYS = [:include, :page].freeze
54
+
55
+ # Finds variables defined in an invoking include, or maybe somewhere else
56
+ # @return variable value or nil
57
+ def dereference_include_variable(name)
58
+ @liquid_context.scopes.each do |scope|
59
+ next if PREDEFINED_SCOPE_KEYS.include? scope.keys.first
60
+
61
+ value = scope[name]
62
+ return value if value
63
+ end
64
+ nil
65
+ end
66
+
67
+ # @return value of variable, or the empty string
68
+ def dereference_variable(name)
69
+ value = @liquid_context[name] # Finds variables named like 'include.my_variable', found in @liquid_context.scopes.first
70
+ value ||= @page[name] if @page # Finds variables named like 'page.my_variable'
71
+ value ||= dereference_include_variable(name)
72
+ value ||= ''
73
+ value
74
+ end
75
+
76
+ # Sets @params by replacing any Liquid variable names with their values
77
+ def liquid_context=(context)
78
+ @liquid_context = context
79
+ @params = @keys_values.map { |k, _v| lookup_variable(k) }
80
+ end
81
+
82
+ def lookup_variable(symbol)
83
+ string = symbol.to_s
84
+ return string unless string.start_with?('{{') && string.end_with?('}}')
85
+
86
+ dereference_variable(string.delete_prefix('{{').delete_suffix('}}'))
87
+ end
88
+
89
+ def page
90
+ @liquid_context.registers[:page]
91
+ end
92
+ 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.2
4
+ version: 1.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Slinn
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-04-06 00:00:00.000000000 Z
11
+ date: 2022-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -66,38 +66,10 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: debase
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: ruby-debug-ide
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
69
  description: 'Jekyll tags pre and noselect, for HTML <pre/> tag, prompts and unselectable
98
70
  text. Can number lines.
99
71
 
100
- '
72
+ '
101
73
  email:
102
74
  - mslinn@mslinn.com
103
75
  executables: []
@@ -112,6 +84,7 @@ files:
112
84
  - jekyll_pre.gemspec
113
85
  - lib/jekyll_pre.rb
114
86
  - lib/jekyll_pre/version.rb
87
+ - lib/jekyll_tag_helper.rb
115
88
  - spec/pre_spec.rb
116
89
  - spec/spec_helper.rb
117
90
  - spec/status_persistence.txt
@@ -142,8 +115,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
115
  - !ruby/object:Gem::Version
143
116
  version: '0'
144
117
  requirements: []
145
- rubygems_version: 3.1.4
146
- signing_key:
118
+ rubygems_version: 3.3.3
119
+ signing_key:
147
120
  specification_version: 4
148
121
  summary: Jekyll tags pre and noselect, for HTML <pre/> tag, prompts and unselectable
149
122
  text. Can number lines.
@@ -151,3 +124,4 @@ test_files:
151
124
  - spec/pre_spec.rb
152
125
  - spec/spec_helper.rb
153
126
  - spec/status_persistence.txt
127
+ ...