mdless 2.0.17 → 2.0.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +0 -6
- data/lib/mdless/array.rb +11 -0
- data/lib/mdless/colors.rb +13 -5
- data/lib/mdless/console.rb +105 -94
- data/lib/mdless/converter.rb +140 -103
- data/lib/mdless/string.rb +94 -8
- data/lib/mdless/taskpaper.rb +79 -9
- data/lib/mdless/version.rb +1 -1
- data/lib/mdless.rb +46 -0
- metadata +17 -2
data/lib/mdless/converter.rb
CHANGED
@@ -4,33 +4,33 @@ require 'yaml'
|
|
4
4
|
module CLIMarkdown
|
5
5
|
class Converter
|
6
6
|
include Colors
|
7
|
-
include Theme
|
8
|
-
|
9
|
-
attr_reader :helpers, :log
|
10
7
|
|
11
8
|
def version
|
12
9
|
"#{CLIMarkdown::EXECUTABLE_NAME} #{CLIMarkdown::VERSION}"
|
13
10
|
end
|
14
11
|
|
12
|
+
def default(option, default)
|
13
|
+
MDLess.options[option] = default if MDLess.options[option].nil?
|
14
|
+
end
|
15
|
+
|
15
16
|
def initialize(args)
|
16
|
-
|
17
|
-
@log.level = Logger::WARN
|
17
|
+
MDLess.log.level = Logger::WARN
|
18
18
|
|
19
|
-
|
19
|
+
MDLess.options = {}
|
20
20
|
config = File.expand_path('~/.config/mdless/config.yml')
|
21
|
-
|
21
|
+
MDLess.options = YAML.load(IO.read(config)) if File.exist?(config)
|
22
22
|
|
23
23
|
optparse = OptionParser.new do |opts|
|
24
24
|
opts.banner = "#{version} by Brett Terpstra\n\n> Usage: #{CLIMarkdown::EXECUTABLE_NAME} [options] [path]\n\n"
|
25
25
|
|
26
|
-
|
26
|
+
default(:color, true)
|
27
27
|
opts.on('-c', '--[no-]color', 'Colorize output (default on)') do |c|
|
28
|
-
|
28
|
+
MDLess.options[:color] = c
|
29
29
|
end
|
30
30
|
|
31
31
|
opts.on('-d', '--debug LEVEL', 'Level of debug messages to output (1-4, 4 to see all messages)') do |level|
|
32
32
|
if level.to_i.positive? && level.to_i < 5
|
33
|
-
|
33
|
+
MDLess.log.level = 5 - level.to_i
|
34
34
|
else
|
35
35
|
puts 'Error: Debug level out of range (1-4)'
|
36
36
|
Process.exit 1
|
@@ -42,64 +42,71 @@ module CLIMarkdown
|
|
42
42
|
exit
|
43
43
|
end
|
44
44
|
|
45
|
-
|
46
|
-
|
45
|
+
default(:local_images, false)
|
46
|
+
default(:remote_images, false)
|
47
47
|
opts.on('-i', '--images=TYPE',
|
48
48
|
'Include [local|remote (both)|none] images in output (requires chafa or imgcat, default none).') do |type|
|
49
49
|
if exec_available('imgcat') || exec_available('chafa')
|
50
50
|
case type
|
51
51
|
when /^(r|b|a)/i
|
52
|
-
|
53
|
-
|
52
|
+
MDLess.options[:local_images] = true
|
53
|
+
MDLess.options[:remote_images] = true
|
54
54
|
when /^l/i
|
55
|
-
|
55
|
+
MDLess.options[:local_images] = true
|
56
56
|
when /^n/
|
57
|
-
|
58
|
-
|
57
|
+
MDLess.options[:local_images] = false
|
58
|
+
MDLess.options[:remote_images] = false
|
59
59
|
end
|
60
60
|
else
|
61
|
-
|
61
|
+
MDLess.log.warn('images turned on but imgcat/chafa not found')
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
65
|
opts.on('-I', '--all-images', 'Include local and remote images in output (requires imgcat or chafa)') do
|
66
66
|
if exec_available('imgcat') || exec_available('chafa') # && ENV['TERM_PROGRAM'] == 'iTerm.app'
|
67
|
-
|
68
|
-
|
67
|
+
MDLess.options[:local_images] = true
|
68
|
+
MDLess.options[:remote_images] = true
|
69
69
|
else
|
70
|
-
|
70
|
+
MDLess.log.warn('images turned on but imgcat/chafa not found')
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
|
74
|
+
default(:list, false)
|
75
75
|
opts.on('-l', '--list', 'List headers in document and exit') do
|
76
|
-
|
76
|
+
MDLess.options[:list] = true
|
77
77
|
end
|
78
78
|
|
79
|
-
|
79
|
+
default(:pager, true)
|
80
80
|
opts.on('-p', '--[no-]pager', 'Formatted output to pager (default on)') do |p|
|
81
|
-
|
81
|
+
MDLess.options[:pager] = p
|
82
82
|
end
|
83
83
|
|
84
|
-
|
84
|
+
default(:pager, true)
|
85
85
|
opts.on('-P', 'Disable pager (same as --no-pager)') do
|
86
|
-
|
86
|
+
MDLess.options[:pager] = false
|
87
87
|
end
|
88
88
|
|
89
|
-
|
89
|
+
default(:section, nil)
|
90
90
|
opts.on('-s', '--section=NUMBER[,NUMBER]',
|
91
91
|
'Output only a headline-based section of the input (numeric from --list)') do |section|
|
92
|
-
|
92
|
+
sections = section.split(/ *, */).map(&:strip)
|
93
|
+
MDLess.options[:section] = sections.map do |sect|
|
94
|
+
if sect =~ /^\d+$/
|
95
|
+
sect.to_i
|
96
|
+
else
|
97
|
+
sect
|
98
|
+
end
|
99
|
+
end
|
93
100
|
end
|
94
101
|
|
95
|
-
|
102
|
+
default(:theme, 'default')
|
96
103
|
opts.on('-t', '--theme=THEME_NAME', 'Specify an alternate color theme to load') do |theme|
|
97
|
-
|
104
|
+
MDLess.options[:theme] = theme
|
98
105
|
end
|
99
106
|
|
100
|
-
|
107
|
+
default(:at_tags, false)
|
101
108
|
opts.on('-@', '--at_tags', 'Highlight @tags and values in the document') do
|
102
|
-
|
109
|
+
MDLess.options[:at_tags] = true
|
103
110
|
end
|
104
111
|
|
105
112
|
opts.on('-v', '--version', 'Display version number') do
|
@@ -107,32 +114,39 @@ module CLIMarkdown
|
|
107
114
|
exit
|
108
115
|
end
|
109
116
|
|
110
|
-
|
117
|
+
default(:width, TTY::Screen.cols)
|
111
118
|
opts.on('-w', '--width=COLUMNS', 'Column width to format for (default: terminal width)') do |columns|
|
112
|
-
|
119
|
+
MDLess.options[:width] = columns.to_i
|
120
|
+
end
|
121
|
+
cols = TTY::Screen.cols
|
122
|
+
MDLess.options[:width] = cols if MDLess.options[:width] > cols
|
123
|
+
|
124
|
+
default(:autolink, true)
|
125
|
+
opts.on('--[no-]autolink', 'Convert bare URLs and emails to <links>') do |p|
|
126
|
+
MDLess.options[:autolink] = p
|
113
127
|
end
|
114
128
|
|
115
|
-
|
129
|
+
default(:inline_footnotes, false)
|
116
130
|
opts.on('--[no-]inline_footnotes',
|
117
131
|
'Display footnotes immediately after the paragraph that references them') do |p|
|
118
|
-
|
132
|
+
MDLess.options[:inline_footnotes] = p
|
119
133
|
end
|
120
134
|
|
121
|
-
|
135
|
+
default(:intra_emphasis, true)
|
122
136
|
opts.on('--[no-]intra-emphasis', 'Parse emphasis inside of words (e.g. Mark_down_)') do |opt|
|
123
|
-
|
137
|
+
MDLess.options[:intra_emphasis] = opt
|
124
138
|
end
|
125
139
|
|
126
|
-
|
140
|
+
default(:lax_spacing, true)
|
127
141
|
opts.on('--[no-]lax-spacing', 'Allow lax spacing') do |opt|
|
128
|
-
|
142
|
+
MDLess.options[:lax_spacing] = opt
|
129
143
|
end
|
130
144
|
|
131
|
-
|
145
|
+
default(:links, :inline)
|
132
146
|
opts.on('--links=FORMAT',
|
133
147
|
'Link style ([inline, reference, paragraph], default inline,
|
134
148
|
"paragraph" will position reference links after each paragraph)') do |fmt|
|
135
|
-
|
149
|
+
MDLess.options[:links] = case fmt
|
136
150
|
when /^:?r/i
|
137
151
|
:reference
|
138
152
|
when /^:?p/i
|
@@ -142,13 +156,13 @@ module CLIMarkdown
|
|
142
156
|
end
|
143
157
|
end
|
144
158
|
|
145
|
-
|
159
|
+
default(:syntax_higlight, false)
|
146
160
|
opts.on('--[no-]syntax', 'Syntax highlight code blocks') do |p|
|
147
|
-
|
161
|
+
MDLess.options[:syntax_higlight] = p
|
148
162
|
end
|
149
163
|
|
150
|
-
|
151
|
-
case
|
164
|
+
MDLess.options[:taskpaper] = if MDLess.options[:taskpaper]
|
165
|
+
case MDLess.options[:taskpaper].to_s
|
152
166
|
when /^[ty1]/
|
153
167
|
true
|
154
168
|
when /^a/
|
@@ -160,7 +174,7 @@ module CLIMarkdown
|
|
160
174
|
false
|
161
175
|
end
|
162
176
|
opts.on('--taskpaper=OPTION', 'Highlight TaskPaper format (true|false|auto)') do |tp|
|
163
|
-
|
177
|
+
MDLess.options[:taskpaper] = case tp
|
164
178
|
when /^[ty1]/
|
165
179
|
true
|
166
180
|
when /^a/
|
@@ -170,14 +184,14 @@ module CLIMarkdown
|
|
170
184
|
end
|
171
185
|
end
|
172
186
|
|
173
|
-
|
187
|
+
default(:update_config, false)
|
174
188
|
opts.on('--update_config', 'Update the configuration file with new keys and current command line options') do
|
175
|
-
|
189
|
+
MDLess.options[:update_config] = true
|
176
190
|
end
|
177
191
|
|
178
|
-
|
192
|
+
default(:wiki_links, false)
|
179
193
|
opts.on('--[no-]wiki-links', 'Highlight [[wiki links]]') do |opt|
|
180
|
-
|
194
|
+
MDLess.options[:wiki_links] = opt
|
181
195
|
end
|
182
196
|
end
|
183
197
|
|
@@ -188,20 +202,21 @@ module CLIMarkdown
|
|
188
202
|
exit 1
|
189
203
|
end
|
190
204
|
|
191
|
-
if !File.exist?(config) ||
|
205
|
+
if !File.exist?(config) || MDLess.options[:update_config]
|
192
206
|
FileUtils.mkdir_p(File.dirname(config))
|
193
207
|
File.open(config, 'w') do |f|
|
194
|
-
opts =
|
208
|
+
opts = MDLess.options.dup
|
195
209
|
opts.delete(:list)
|
196
210
|
opts.delete(:section)
|
197
211
|
opts.delete(:update_config)
|
212
|
+
opts = opts.keys.map(&:to_s).sort.map { |k| [k.to_sym, opts[k.to_sym]] }.to_h
|
198
213
|
f.puts YAML.dump(opts)
|
199
214
|
warn "Config file saved to #{config}"
|
200
215
|
end
|
201
216
|
end
|
202
217
|
|
203
|
-
|
204
|
-
|
218
|
+
MDLess.cols = MDLess.options[:width] - 2
|
219
|
+
|
205
220
|
@output = ''
|
206
221
|
@headers = []
|
207
222
|
@setheaders = []
|
@@ -211,19 +226,15 @@ module CLIMarkdown
|
|
211
226
|
@footnotes = {}
|
212
227
|
|
213
228
|
renderer = Redcarpet::Render::Console.new
|
214
|
-
renderer.theme = @theme
|
215
|
-
renderer.cols = @cols
|
216
|
-
renderer.log = @log
|
217
|
-
renderer.options = @options
|
218
229
|
|
219
230
|
markdown = Redcarpet::Markdown.new(renderer,
|
220
|
-
no_intra_emphasis:
|
221
|
-
autolink:
|
231
|
+
no_intra_emphasis: !MDLess.options[:intra_emphasis],
|
232
|
+
autolink: MDLess.options[:autolink],
|
222
233
|
fenced_code_blocks: true,
|
223
234
|
footnotes: true,
|
224
235
|
hard_wrap: false,
|
225
236
|
highlight: true,
|
226
|
-
lax_spacing:
|
237
|
+
lax_spacing: MDLess.options[:lax_spacing],
|
227
238
|
quote: false,
|
228
239
|
space_after_headers: false,
|
229
240
|
strikethrough: true,
|
@@ -234,9 +245,9 @@ module CLIMarkdown
|
|
234
245
|
if !args.empty?
|
235
246
|
files = args.delete_if { |f| !File.exist?(f) }
|
236
247
|
files.each do |file|
|
237
|
-
|
238
|
-
|
239
|
-
|
248
|
+
MDLess.log.info(%(Processing "#{file}"))
|
249
|
+
MDLess.file = file
|
250
|
+
|
240
251
|
begin
|
241
252
|
input = IO.read(file).force_encoding('utf-8')
|
242
253
|
rescue StandardError
|
@@ -247,25 +258,27 @@ module CLIMarkdown
|
|
247
258
|
input.scrub!
|
248
259
|
input.gsub!(/\r?\n/, "\n")
|
249
260
|
|
250
|
-
if
|
251
|
-
|
261
|
+
if MDLess.options[:taskpaper] == :auto
|
262
|
+
MDLess.options[:taskpaper] = if CLIMarkdown::TaskPaper.is_taskpaper?(input)
|
263
|
+
MDLess.log.info('TaskPaper detected')
|
264
|
+
true
|
265
|
+
else
|
266
|
+
false
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
if MDLess.options[:list]
|
271
|
+
if MDLess.options[:taskpaper]
|
272
|
+
puts CLIMarkdown::TaskPaper.list_projects(input)
|
273
|
+
else
|
274
|
+
puts list_headers(input)
|
275
|
+
end
|
252
276
|
Process.exit 0
|
253
277
|
else
|
254
|
-
if
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
elsif CLIMarkdown::TaskPaper.is_taskpaper?(input)
|
259
|
-
@log.info('TaskPaper document detected')
|
260
|
-
true
|
261
|
-
else
|
262
|
-
false
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
if @options[:taskpaper]
|
267
|
-
input = CLIMarkdown::TaskPaper.highlight(input, @theme)
|
268
|
-
@output = input.highlight_tags(@theme, @log)
|
278
|
+
if MDLess.options[:taskpaper]
|
279
|
+
input = input.color_meta(MDLess.cols)
|
280
|
+
input = CLIMarkdown::TaskPaper.highlight(input)
|
281
|
+
@output = input.highlight_tags
|
269
282
|
else
|
270
283
|
@output = markdown.render(input)
|
271
284
|
end
|
@@ -273,14 +286,34 @@ module CLIMarkdown
|
|
273
286
|
end
|
274
287
|
printout
|
275
288
|
elsif !$stdin.isatty
|
276
|
-
|
289
|
+
MDLess.file = nil
|
277
290
|
input = $stdin.read.scrub
|
278
291
|
input.gsub!(/\r?\n/, "\n")
|
279
|
-
|
280
|
-
|
292
|
+
|
293
|
+
if MDLess.options[:taskpaper] == :auto
|
294
|
+
MDLess.options[:taskpaper] = if CLIMarkdown::TaskPaper.is_taskpaper?(input)
|
295
|
+
MDLess.log.info('TaskPaper detected')
|
296
|
+
true
|
297
|
+
else
|
298
|
+
false
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
if MDLess.options[:list]
|
303
|
+
if MDLess.options[:taskpaper]
|
304
|
+
puts CLIMarkdown::TaskPaper.list_projects(input)
|
305
|
+
else
|
306
|
+
puts list_headers(input)
|
307
|
+
end
|
281
308
|
Process.exit 0
|
282
309
|
else
|
283
|
-
|
310
|
+
if MDLess.options[:taskpaper]
|
311
|
+
input = input.color_meta(MDLess.cols)
|
312
|
+
input = CLIMarkdown::TaskPaper.highlight(input)
|
313
|
+
@output = input.highlight_tags
|
314
|
+
else
|
315
|
+
@output = markdown.render(input)
|
316
|
+
end
|
284
317
|
end
|
285
318
|
printout
|
286
319
|
else
|
@@ -292,17 +325,17 @@ module CLIMarkdown
|
|
292
325
|
def color(key)
|
293
326
|
val = nil
|
294
327
|
keys = key.split(/[ ,>]/)
|
295
|
-
if
|
296
|
-
val =
|
328
|
+
if MDLess.theme.key?(keys[0])
|
329
|
+
val = MDLess.theme[keys.shift]
|
297
330
|
else
|
298
|
-
|
331
|
+
MDLess.log.error("Invalid theme key: #{key}") unless keys[0] =~ /^text/
|
299
332
|
return c([:reset])
|
300
333
|
end
|
301
334
|
keys.each do |k|
|
302
335
|
if val.key?(k)
|
303
336
|
val = val[k]
|
304
337
|
else
|
305
|
-
|
338
|
+
MDLess.log.error("Invalid theme key: #{k}")
|
306
339
|
return c([:reset])
|
307
340
|
end
|
308
341
|
end
|
@@ -394,8 +427,8 @@ module CLIMarkdown
|
|
394
427
|
|
395
428
|
def clean_markers(input)
|
396
429
|
input.gsub!(/^(\e\[[\d;]+m)?[%~] ?/, '\1')
|
397
|
-
input.gsub!(/^(\e\[[\d;]+m)*>(\e\[[\d;]+m)?( +)/, ' \3\1\2')
|
398
|
-
input.gsub!(/^(\e\[[\d;]+m)*>(\e\[[\d;]+m)?/, '\1\2')
|
430
|
+
# input.gsub!(/^(\e\[[\d;]+m)*>(\e\[[\d;]+m)?( +)/, ' \3\1\2')
|
431
|
+
# input.gsub!(/^(\e\[[\d;]+m)*>(\e\[[\d;]+m)?/, '\1\2')
|
399
432
|
input.gsub!(/(\e\[[\d;]+m)?@@@(\e\[[\d;]+m)?$/, '')
|
400
433
|
input
|
401
434
|
end
|
@@ -424,7 +457,7 @@ module CLIMarkdown
|
|
424
457
|
block.split(/\n/).map do |l|
|
425
458
|
new_code_line = l.gsub(/\t/, ' ')
|
426
459
|
orig_length = new_code_line.size + 8 + eol.size
|
427
|
-
pad_count = [
|
460
|
+
pad_count = [MDLess.cols - orig_length, 0].max
|
428
461
|
|
429
462
|
[
|
430
463
|
new_code_line,
|
@@ -448,11 +481,11 @@ module CLIMarkdown
|
|
448
481
|
IO.select [input]
|
449
482
|
|
450
483
|
pager = which_pager
|
451
|
-
|
484
|
+
MDLess.log.info("Using #{pager} as pager")
|
452
485
|
begin
|
453
486
|
exec(pager.join(' '))
|
454
487
|
rescue SystemCallError => e
|
455
|
-
|
488
|
+
MDLess.log.error(e)
|
456
489
|
exit 1
|
457
490
|
end
|
458
491
|
end
|
@@ -470,21 +503,25 @@ module CLIMarkdown
|
|
470
503
|
end
|
471
504
|
|
472
505
|
def printout
|
473
|
-
|
474
|
-
|
475
|
-
|
506
|
+
if MDLess.options[:taskpaper]
|
507
|
+
out = @output
|
508
|
+
else
|
509
|
+
out = @output.rstrip.split(/\n/).map do |p|
|
510
|
+
p.wrap(MDLess.cols, color('text'))
|
511
|
+
end.join("\n")
|
512
|
+
end
|
476
513
|
|
477
514
|
unless out.size&.positive?
|
478
|
-
|
515
|
+
MDLess.log.warn 'No results'
|
479
516
|
Process.exit
|
480
517
|
end
|
481
518
|
|
482
519
|
out = clean_markers(out)
|
483
520
|
out = "#{out.gsub(/\n{2,}/m, "\n\n")}#{xc}"
|
484
521
|
|
485
|
-
out.uncolor! unless
|
522
|
+
out.uncolor! unless MDLess.options[:color]
|
486
523
|
|
487
|
-
if
|
524
|
+
if MDLess.options[:pager]
|
488
525
|
page(out)
|
489
526
|
else
|
490
527
|
$stdout.print out.rstrip
|
@@ -507,7 +544,7 @@ module CLIMarkdown
|
|
507
544
|
if f.strip =~ /[ |]/
|
508
545
|
f
|
509
546
|
elsif f == 'most'
|
510
|
-
|
547
|
+
MDLess.log.warn('most not allowed as pager')
|
511
548
|
false
|
512
549
|
else
|
513
550
|
system "which #{f}", out: File::NULL, err: File::NULL
|
data/lib/mdless/string.rb
CHANGED
@@ -4,20 +4,28 @@
|
|
4
4
|
class ::String
|
5
5
|
include CLIMarkdown::Colors
|
6
6
|
|
7
|
-
def
|
7
|
+
def clean_empty_lines
|
8
|
+
gsub(/^[ \t]+$/, '')
|
9
|
+
end
|
10
|
+
|
11
|
+
def clean_empty_lines!
|
12
|
+
replace clean_empty_lines
|
13
|
+
end
|
14
|
+
|
15
|
+
def color(key)
|
8
16
|
val = nil
|
9
17
|
keys = key.split(/[ ,>]/)
|
10
|
-
if theme.key?(keys[0])
|
11
|
-
val = theme[keys.shift]
|
18
|
+
if MDLess.theme.key?(keys[0])
|
19
|
+
val = MDLess.theme[keys.shift]
|
12
20
|
else
|
13
|
-
log.error("Invalid theme key: #{key}") unless keys[0] =~ /^text/
|
21
|
+
MDLess.log.error("Invalid theme key: #{key}") unless keys[0] =~ /^text/
|
14
22
|
return c([:reset])
|
15
23
|
end
|
16
24
|
keys.each do |k|
|
17
25
|
if val.key?(k)
|
18
26
|
val = val[k]
|
19
27
|
else
|
20
|
-
log.error("Invalid theme key: #{k}")
|
28
|
+
MDLess.log.error("Invalid theme key: #{k}")
|
21
29
|
return c([:reset])
|
22
30
|
end
|
23
31
|
end
|
@@ -30,9 +38,75 @@ class ::String
|
|
30
38
|
end
|
31
39
|
end
|
32
40
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
41
|
+
def to_rx(distance: 2, string_start: false)
|
42
|
+
chars = downcase.split(//)
|
43
|
+
pre = string_start ? '^' : '^.*?'
|
44
|
+
/#{pre}#{chars.join(".{,#{distance}}")}.*?$/
|
45
|
+
end
|
46
|
+
|
47
|
+
def clean_header_ids!
|
48
|
+
replace clean_header_ids
|
49
|
+
end
|
50
|
+
|
51
|
+
def clean_header_ids
|
52
|
+
gsub(/ +\[.*?\] *$/, '').gsub(/ *\{#.*?\} *$/, '').strip
|
53
|
+
end
|
54
|
+
|
55
|
+
def color_meta(cols)
|
56
|
+
@cols = cols
|
57
|
+
input = dup
|
58
|
+
input.clean_empty_lines!
|
59
|
+
|
60
|
+
in_yaml = false
|
61
|
+
first_line = input.split("\n").first
|
62
|
+
if first_line =~ /(?i-m)^---[ \t]*?$/
|
63
|
+
MDLess.log.info('Found YAML')
|
64
|
+
# YAML
|
65
|
+
in_yaml = true
|
66
|
+
input.sub!(/(?i-m)^---[ \t]*\n([\s\S]*?)\n[-.]{3}[ \t]*\n/m) do
|
67
|
+
m = Regexp.last_match
|
68
|
+
MDLess.log.info('Processing YAML Header')
|
69
|
+
lines = m[0].split(/\n/)
|
70
|
+
longest = lines.inject { |memo, word| memo.length > word.length ? memo : word }.length
|
71
|
+
longest = longest < @cols ? longest + 1 : @cols
|
72
|
+
lines.map do |line|
|
73
|
+
if line =~ /^[-.]{3}\s*$/
|
74
|
+
line = "#{color('metadata marker')}#{'%' * longest}"
|
75
|
+
else
|
76
|
+
line.sub!(/^(.*?:)[ \t]+(\S)/, '\1 \2')
|
77
|
+
line = "#{color('metadata color')}#{line}"
|
78
|
+
end
|
79
|
+
|
80
|
+
line += "\u00A0" * (longest - line.uncolor.strip.length) + xc
|
81
|
+
line
|
82
|
+
end.join("\n") + "#{xc}\n"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
if !in_yaml && first_line =~ /(?i-m)^[\w ]+:\s+\S+/
|
87
|
+
MDLess.log.info('Found MMD Headers')
|
88
|
+
input.sub!(/(?i-m)^([\S ]+:[\s\S]*?)+(?=\n\n)/) do |mmd|
|
89
|
+
lines = mmd.split(/\n/)
|
90
|
+
return mmd if lines.count > 20
|
91
|
+
|
92
|
+
longest = lines.inject { |memo, word| memo.length > word.length ? memo : word }.length
|
93
|
+
longest = longest < @cols ? longest + 1 : @cols
|
94
|
+
lines.map do |line|
|
95
|
+
line.sub!(/^(.*?:)[ \t]+(\S)/, '\1 \2')
|
96
|
+
line = "#{color('metadata color')}#{line}"
|
97
|
+
line += "\u00A0" * (longest - line.uncolor.strip.length)
|
98
|
+
line + xc
|
99
|
+
end.join("\n") + "#{"\u00A0" * longest}#{xc}\n"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
input
|
104
|
+
end
|
105
|
+
|
106
|
+
def highlight_tags
|
107
|
+
log = MDLess.log
|
108
|
+
tag_color = color('at_tags tag')
|
109
|
+
value_color = color('at_tags value')
|
36
110
|
gsub(/(?<pre>\s|m)(?<tag>@[^ \].?!,("']+)(?:(?<lparen>\()(?<value>.*?)(?<rparen>\)))?/) do
|
37
111
|
m = Regexp.last_match
|
38
112
|
last_color = m.pre_match.last_color_code
|
@@ -58,4 +132,16 @@ class ::String
|
|
58
132
|
def scrub!
|
59
133
|
replace scrub
|
60
134
|
end
|
135
|
+
|
136
|
+
def valid_pygments_theme?
|
137
|
+
return false unless TTY::Which.exist?('pygmentize')
|
138
|
+
|
139
|
+
MDLess.pygments_styles.include?(self)
|
140
|
+
end
|
141
|
+
|
142
|
+
def valid_lexer?
|
143
|
+
return false unless TTY::Which.exist?('pygmentize')
|
144
|
+
|
145
|
+
MDLess.pygments_lexers.include?(self.downcase)
|
146
|
+
end
|
61
147
|
end
|