Skip to content

Commit a2d47f1

Browse files
committed
Added number option
1 parent 5405992 commit a2d47f1

10 files changed

+138
-29
lines changed

.rspec

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
--color
2-
--format progress
2+
--format documentation
3+
--require spec_helper

.vscode/launch.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@
2424
],
2525
"cwd": "${workspaceRoot}",
2626
"name": "RSpec - active spec file only",
27-
"program": "${env:HOME}/.rbenv/shims/rspec",
27+
"program": "${env:HOME}/.gems/bin/rspec",
2828
"showDebuggerOutput": false,
2929
"request": "launch",
30+
"see": "https://relishapp.com/rspec/rspec-core/docs/command-line",
3031
"type": "Ruby",
3132
"useBundler": true,
3233
},
@@ -37,8 +38,9 @@
3738
],
3839
"cwd": "${workspaceRoot}",
3940
"name": "RSpec - all",
40-
"program": "${env:HOME}/.rbenv/shims/rspec",
41+
"program": "${env:HOME}/.gems/bin/rspec",
4142
"request": "launch",
43+
"see": "https://relishapp.com/rspec/rspec-core/docs/command-line",
4244
"showDebuggerOutput": false,
4345
"type": "Ruby",
4446
"useBundler": true,

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 1.1.0 / 2022-03-31
2+
* Added `number` option, which generates unselectable line numbers for contents
3+
14
## 1.0.0 / 2022-03-13
25
* Made into a Ruby gem and published on RubyGems.org as [jekyll_pre](https://rubygems.org/gems/jekyll_pre).
36
* `bin/attach` script added for debugging

Gemfile.lock

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
PATH
22
remote: .
33
specs:
4-
jekyll_pre (1.0.0)
4+
jekyll_pre (1.1.0)
55
jekyll (>= 3.5.0)
66
jekyll_plugin_logger
7+
key-value-parser
8+
shellwords
79

810
GEM
911
remote: https://rubygems.org/
@@ -12,7 +14,7 @@ GEM
1214
public_suffix (>= 2.0.2, < 5.0)
1315
ast (2.4.2)
1416
colorator (1.1.0)
15-
concurrent-ruby (1.1.9)
17+
concurrent-ruby (1.1.10)
1618
debase (0.2.4.1)
1719
debase-ruby_core_source (>= 0.10.2)
1820
debase-ruby_core_source (0.10.14)
@@ -47,7 +49,8 @@ GEM
4749
listen (~> 3.0)
4850
jekyll_plugin_logger (2.0.0)
4951
jekyll (>= 3.5.0)
50-
kramdown (2.3.1)
52+
key-value-parser (0.0.2)
53+
kramdown (2.3.2)
5154
rexml
5255
kramdown-parser-gfm (1.1.0)
5356
kramdown (~> 2.0)
@@ -100,6 +103,7 @@ GEM
100103
safe_yaml (1.0.5)
101104
sassc (2.4.0)
102105
ffi (~> 1.9)
106+
shellwords (0.1.0)
103107
terminal-table (2.0.0)
104108
unicode-display_width (~> 1.1, >= 1.1.1)
105109
unicode-display_width (1.8.0)

jekyll_pre.gemspec

+4-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
2525
spec.authors = ["Mike Slinn"]
2626
spec.bindir = "exe"
2727
spec.description = <<~END_OF_DESC
28-
Jekyll tags pre and noselect, for HTML <pre/> tag, prompts and unselectable text.
28+
Jekyll tags pre and noselect, for HTML <pre/> tag, prompts and unselectable text. Can number lines.
2929
END_OF_DESC
3030
spec.email = ["[email protected]"]
3131
spec.files = Dir[".rubocop.yml", "LICENSE.*", "Rakefile", "{lib,spec}/**/*", "*.gemspec", "*.md"]
@@ -46,12 +46,14 @@ Gem::Specification.new do |spec|
4646
END_MESSAGE
4747
spec.require_paths = ["lib"]
4848
spec.required_ruby_version = ">= 2.6.0"
49-
spec.summary = "Jekyll tags pre and noselect, for HTML <pre/> tag, prompts and unselectable text."
49+
spec.summary = "Jekyll tags pre and noselect, for HTML <pre/> tag, prompts and unselectable text. Can number lines."
5050
spec.test_files = spec.files.grep(%r!^(test|spec|features)/!)
5151
spec.version = JekyllPre::VERSION
5252

5353
spec.add_dependency "jekyll", ">= 3.5.0"
5454
spec.add_dependency "jekyll_plugin_logger"
55+
spec.add_dependency "key-value-parser"
56+
spec.add_dependency "shellwords"
5557

5658
spec.add_development_dependency "debase"
5759
# spec.add_development_dependency "rubocop-jekyll"

lib/jekyll_pre.rb

+46-20
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ module JekyllPluginPreName
3131
class PreTagBlock < Liquid::Block
3232
@@prefix = "<button class='copyBtn' data-clipboard-target="
3333
@@suffix = " title='Copy to clipboard'><img src='/assets/images/clippy.svg' " \
34-
"alt='Copy to clipboard' style='width: 13px'></button>"
34+
"alt='Copy to clipboard' style='width: 13px'></button>"
3535

3636
def self.make_copy_button(pre_id)
3737
"#{@@prefix}'##{pre_id}'#{@@suffix}"
3838
end
3939

40-
def self.make_pre(make_copy_button, label, content)
40+
def self.make_pre(make_copy_button, number_lines, label, content)
4141
label = if label.to_s.empty?
4242
""
4343
elsif label.to_s.downcase.strip == "shell"
@@ -47,47 +47,73 @@ def self.make_pre(make_copy_button, label, content)
4747
end
4848
pre_id = "id#{SecureRandom.hex(6)}"
4949
copy_button = make_copy_button ? PreTagBlock.make_copy_button(pre_id) : ""
50+
content = PreTagBlock.number_content(content) if number_lines
5051
"#{label}<pre data-lt-active='false' class='maxOneScreenHigh copyContainer' id='#{pre_id}'>#{copy_button}#{content.strip}</pre>"
5152
end
5253

53-
# @param tag_name [String] is the name of the tag, which we already know.
54-
# @param text [Hash, String, Liquid::Tag::Parser] the arguments from the web page.
55-
# @param tokens [Liquid::ParseContext] tokenized command line
54+
def self.number_content(content)
55+
lines = content.split("\n")
56+
digits = lines.length.to_s.length
57+
i = 0
58+
numbered_content = lines.map do |line|
59+
i += 1
60+
number = i.to_s.rjust(digits, " ")
61+
"<span class='unselectable'> #{number}: </span>#{line}"
62+
end
63+
result = numbered_content.join("\n")
64+
result += "\n" unless result.end_with?("\n")
65+
result
66+
end
67+
68+
# @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.
70+
# @param _tokens [Liquid::ParseContext] tokenized command line
5671
# @return [void]
57-
def initialize(tag_name, text, tokens)
58-
super(tag_name, text, tokens)
59-
text = "" if text.nil?
60-
text.strip!
61-
@make_copy_button = text.include? "copyButton"
62-
remaining_text = text.sub("copyButton", "").strip
72+
def initialize(_tag_name, argument_string, _tokens)
73+
super
74+
argument_string = "" if argument_string.nil?
75+
argument_string.strip!
76+
6377
@logger = PluginMetaLogger.instance.new_logger(self)
64-
@logger.debug { "@make_copy_button = '#{@make_copy_button}'; text = '#{text}'; remaining_text = '#{remaining_text}'" }
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+
6585
@label = remaining_text
86+
87+
@logger.debug { "@make_copy_button = '#{@make_copy_button}'; argument_string = '#{argument_string}'; remaining_text = '#{remaining_text}'" }
6688
end
6789

6890
# Method prescribed by the Jekyll plugin lifecycle.
6991
# @return [String]
7092
def render(context)
7193
content = super
7294
@logger.debug { "@make_copy_button = '#{@make_copy_button}'; @label = '#{@label}'" }
73-
PreTagBlock.make_pre(@make_copy_button, @label, content)
95+
PreTagBlock.make_pre(@make_copy_button, @number_lines, @label, content)
7496
end
7597
end
7698

7799
# """\\{% noselect %} or \\{% noselect this all gets copied.
78100
# Also, space before the closing percent is signficant %}"""
79101
class UnselectableTag < Liquid::Tag
80-
def initialize(tag_name, text, tokens)
81-
super(tag_name, text, tokens)
82-
@content = text
102+
# @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.
104+
# @param _tokens [Liquid::ParseContext] tokenized command line
105+
# @return [void]
106+
def initialize(_tag_name, argument_string, _tokens)
107+
super
83108
@logger = PluginMetaLogger.instance.new_logger(self)
84-
@logger.debug { "UnselectableTag: content1= '#{@content}'" }
85-
@content = "$ " if @content.nil? || @content.empty?
86-
@logger.debug { "UnselectableTag: content2= '#{@content}'" }
109+
110+
@argument_string = argument_string
111+
@argument_string = "$ " if @argument_string.nil? || @argument_string.empty?
112+
@logger.debug { "UnselectableTag: argument_string= '#{@argument_string}'" }
87113
end
88114

89115
def render(_)
90-
"<span class='unselectable'>#{@content}</span>"
116+
"<span class='unselectable'>#{@argument_string}</span>"
91117
end
92118
end
93119

lib/jekyll_pre/version.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module JekyllPre
4-
VERSION = "1.0.0"
4+
VERSION = "1.1.0"
55
end

spec/pre_spec.rb

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# frozen_string_literal: true
2+
3+
require "fileutils"
4+
require "jekyll"
5+
require "key_value_parser"
6+
require "shellwords"
7+
require_relative "../lib/jekyll_pre"
8+
9+
RSpec.describe(PreTagBlock) do
10+
it "parses arguments" do
11+
argv = Shellwords.split "number copyButton shell"
12+
options = KeyValueParser.new.parse(argv)
13+
# puts options.map { |k, v| "#{k} = #{v}" }.join("\n")
14+
15+
expect(options[:copyButton]).to be true
16+
expect(options[:number]).to be true
17+
expect(options[:shell]).to be true
18+
end
19+
20+
it "numbers content lines" do
21+
content = <<~END_CONTENT
22+
Line 1
23+
Line 2
24+
Line 3
25+
Line 4
26+
Line 5
27+
Line 6
28+
Line 7
29+
Line 8
30+
Line 9
31+
Line 10
32+
END_CONTENT
33+
numbered_content = PreTagBlock.number_content(content)
34+
expected_content = <<~END_CONTENT
35+
<span class='unselectable'> 1: </span>Line 1
36+
<span class='unselectable'> 2: </span> Line 2
37+
<span class='unselectable'> 3: </span> Line 3
38+
<span class='unselectable'> 4: </span> Line 4
39+
<span class='unselectable'> 5: </span> Line 5
40+
<span class='unselectable'> 6: </span>Line 6
41+
<span class='unselectable'> 7: </span>Line 7
42+
<span class='unselectable'> 8: </span> Line 8
43+
<span class='unselectable'> 9: </span> Line 9
44+
<span class='unselectable'> 10: </span>Line 10
45+
END_CONTENT
46+
expect(numbered_content).to eq(expected_content)
47+
end
48+
end

spec/spec_helper.rb

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# frozen_string_literal: true
2+
3+
require "jekyll"
4+
require "fileutils"
5+
require "key_value_parser"
6+
require "shellwords"
7+
8+
require_relative "../lib/jekyll_pre"
9+
10+
Jekyll.logger.log_level = :info
11+
12+
RSpec.configure do |config|
13+
config.filter_run :focus
14+
config.order = "random"
15+
config.run_all_when_everything_filtered = true
16+
17+
# See https://relishapp.com/rspec/rspec-core/docs/command-line/only-failures
18+
config.example_status_persistence_file_path = "spec/status_persistence.txt"
19+
end

spec/status_persistence.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
example_id | status | run_time |
2+
----------------------- | ------ | --------------- |
3+
./spec/pre_spec.rb[1:1] | passed | 0.00253 seconds |
4+
./spec/pre_spec.rb[1:2] | passed | 0.00203 seconds |

0 commit comments

Comments
 (0)