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 +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +2 -1
- data/lib/jekyll_pre/version.rb +1 -1
- data/lib/jekyll_pre.rb +43 -27
- data/lib/jekyll_tag_helper.rb +90 -0
- data/spec/pre_spec.rb +17 -0
- data/spec/status_persistence.txt +3 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be2fcd1765446ab64973e355acb073057dea3c98ed1be553362b5b755e5453fb
|
4
|
+
data.tar.gz: 33b14de234b5764673af3c9380d6ae32fa5a429294f7ee5f53d094aa63bf1f87
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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/lib/jekyll_pre/version.rb
CHANGED
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
|
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,
|
85
|
+
def initialize(_tag_name, markup, _tokens)
|
73
86
|
super
|
74
|
-
|
75
|
-
|
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
|
-
@
|
83
|
-
|
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(
|
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
|
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,
|
122
|
+
def initialize(_tag_name, markup, _tokens)
|
107
123
|
super
|
108
124
|
@logger = PluginMetaLogger.instance.new_logger(self)
|
109
125
|
|
110
|
-
@
|
111
|
-
@
|
112
|
-
@logger.debug { "UnselectableTag:
|
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'>#{@
|
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("&", "&")
|
11
|
+
.gsub("{", "{")
|
12
|
+
.gsub("}", "}")
|
13
|
+
.gsub("<", "<")
|
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
|
data/spec/status_persistence.txt
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
example_id | status | run_time |
|
2
2
|
----------------------- | ------ | --------------- |
|
3
|
-
./spec/pre_spec.rb[1:1] | passed | 0.
|
4
|
-
./spec/pre_spec.rb[1:2] | passed | 0.
|
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.
|
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-
|
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
|