mdless 1.0.37 → 2.0.1

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: 79e5b5ce0612ca6b58434e65c449761b9f59e9722f3e7ae6abc107a975b793e8
4
- data.tar.gz: 4e09831ca7e91aaf6d78dfbec3d7eb74ca8e372c51ec202188c4aefedd3e30c8
3
+ metadata.gz: c645677f1a192348600bf54180afe501b76888d14bad121c4577090ca81718b2
4
+ data.tar.gz: 7e82688bd079cede12e529a813c628297070b91b47d68276e54b368b7155bc25
5
5
  SHA512:
6
- metadata.gz: 304f7590b03f8ab1efb52ef6142a57911167b49d2af7b616f41ae71136aab5fc47a0f772074b76f69c74fc142588be71ee2c507a93bb07c5efb63fb2e92db026
7
- data.tar.gz: 4f2d406c790457383b6b87f81ab5c9b7a2dd92a9c716582fe3ebf5a58d385a11308fee5c2b405bf8a21e4ee283dc2b5e284bce6b74e273abdb3051056f9c713b
6
+ metadata.gz: 830a9aea162d1481ceca6a5dd9cfed3e1a46821a4f1ceaae0d77a843d19a9d0515338025120bc8cfd6bd55fec449009782be872f6558d01d55155bfea9699804
7
+ data.tar.gz: ae994c34ece07c3fa05cad41c0e28c866e642dd268a6d175e8746bbd1c8e4d492ca1eef4b943ba506b4769079958296f0ac885e3a10eadc37d595164618db349
data/bin/mdless CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby
1
+ #!/usr/bin/env ruby -W1
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'mdless'
@@ -1,6 +1,5 @@
1
1
  require 'fileutils'
2
2
  require 'yaml'
3
- require 'fileutils'
4
3
 
5
4
  module CLIMarkdown
6
5
  class Converter
@@ -14,23 +13,26 @@ module CLIMarkdown
14
13
  end
15
14
 
16
15
  def initialize(args)
17
- @log = Logger.new(STDERR)
16
+ @log = Logger.new($stderr)
18
17
  @log.level = Logger::ERROR
19
18
 
20
19
  @options = {}
20
+ config = File.expand_path('~/.config/mdless/config.yml')
21
+ @options = YAML.load(IO.read(config)) if File.exist?(config)
22
+
21
23
  optparse = OptionParser.new do |opts|
22
24
  opts.banner = "#{version} by Brett Terpstra\n\n> Usage: #{CLIMarkdown::EXECUTABLE_NAME} [options] [path]\n\n"
23
25
 
24
- @options[:color] = true
26
+ @options[:color] ||= true
25
27
  opts.on('-c', '--[no-]color', 'Colorize output (default on)') do |c|
26
28
  @options[:color] = c
27
29
  end
28
30
 
29
- opts.on('-d', '--debug LEVEL', 'Level of debug messages to output') do |level|
30
- if level.to_i > 0 && level.to_i < 5
31
+ opts.on('-d', '--debug LEVEL', 'Level of debug messages to output (1-4, 4 to see all messages)') do |level|
32
+ if level.to_i.positive? && level.to_i < 5
31
33
  @log.level = 5 - level.to_i
32
34
  else
33
- $stderr.puts "Error: Log level out of range (1-4)"
35
+ puts 'Error: Debug level out of range (1-4)'
34
36
  Process.exit 1
35
37
  end
36
38
  end
@@ -40,18 +42,19 @@ module CLIMarkdown
40
42
  exit
41
43
  end
42
44
 
43
- @options[:local_images] = false
44
- @options[:remote_images] = false
45
- opts.on('-i', '--images=TYPE', 'Include [local|remote (both)] images in output (requires chafa or imgcat, default NONE). imgcat does not work with pagers, use with -P' ) do |type|
46
- unless exec_available('imgcat') || exec_available('chafa')# && ENV['TERM_PROGRAM'] == 'iTerm.app'
47
- @log.warn('images turned on but imgcat/chafa not found')
48
- else
45
+ @options[:local_images] ||= false
46
+ @options[:remote_images] ||= false
47
+ opts.on('-i', '--images=TYPE',
48
+ 'Include [local|remote (both)] images in output (requires chafa or imgcat, default NONE).') do |type|
49
+ if exec_available('imgcat') || exec_available('chafa')
49
50
  if type =~ /^(r|b|a)/i
50
51
  @options[:local_images] = true
51
52
  @options[:remote_images] = true
52
53
  elsif type =~ /^l/i
53
54
  @options[:local_images] = true
54
55
  end
56
+ else
57
+ @log.warn('images turned on but imgcat/chafa not found')
55
58
  end
56
59
  end
57
60
  opts.on('-I', '--all-images', 'Include local and remote images in output (requires imgcat or chafa)') do
@@ -63,19 +66,23 @@ module CLIMarkdown
63
66
  end
64
67
  end
65
68
 
66
- @options[:links] = :inline
67
- opts.on('--links=FORMAT', 'Link style ([inline, reference], default inline) [NOT CURRENTLY IMPLEMENTED]') do |format|
68
- if format =~ /^r/i
69
- @options[:links] = :reference
70
- end
69
+ @options[:syntax_higlight] ||= false
70
+ opts.on('--syntax', 'Syntax highlight code blocks') do |p|
71
+ @options[:syntax_higlight] = p
72
+ end
73
+
74
+ @options[:links] ||= :inline
75
+ opts.on('--links=FORMAT',
76
+ 'Link style ([inline, reference], default inline) [NOT CURRENTLY IMPLEMENTED]') do |format|
77
+ @options[:links] = :reference if format =~ /^r/i
71
78
  end
72
79
 
73
- @options[:list] = false
74
- opts.on('-l', '--list', 'List headers in document and exit' ) do
80
+ @options[:list] ||= false
81
+ opts.on('-l', '--list', 'List headers in document and exit') do
75
82
  @options[:list] = true
76
83
  end
77
84
 
78
- @options[:pager] = true
85
+ @options[:pager] ||= true
79
86
  opts.on('-p', '--[no-]pager', 'Formatted output to pager (default on)') do |p|
80
87
  @options[:pager] = p
81
88
  end
@@ -84,12 +91,13 @@ module CLIMarkdown
84
91
  @options[:pager] = false
85
92
  end
86
93
 
87
- @options[:section] = nil
88
- opts.on('-s', '--section=NUMBER[,NUMBER]', 'Output only a headline-based section of the input (numeric from --list)') do |section|
94
+ @options[:section] ||= nil
95
+ opts.on('-s', '--section=NUMBER[,NUMBER]',
96
+ 'Output only a headline-based section of the input (numeric from --list)') do |section|
89
97
  @options[:section] = section.split(/ *, */).map(&:strip).map(&:to_i)
90
98
  end
91
99
 
92
- @options[:theme] = 'default'
100
+ @options[:theme] ||= 'default'
93
101
  opts.on('-t', '--theme=THEME_NAME', 'Specify an alternate color theme to load') do |theme|
94
102
  @options[:theme] = theme
95
103
  end
@@ -103,6 +111,12 @@ module CLIMarkdown
103
111
  opts.on('-w', '--width=COLUMNS', 'Column width to format for (default: terminal width)') do |columns|
104
112
  @options[:width] = columns.to_i
105
113
  end
114
+
115
+ @options[:inline_footnotes] ||= false
116
+ opts.on('--[no-]inline_footnotes',
117
+ 'Display footnotes immediately after the paragraph that references them') do |p|
118
+ @options[:inline_footnotes] = p
119
+ end
106
120
  end
107
121
 
108
122
  begin
@@ -112,8 +126,19 @@ module CLIMarkdown
112
126
  exit 1
113
127
  end
114
128
 
129
+ unless File.exist?(config)
130
+ FileUtils.mkdir_p(File.dirname(config))
131
+ File.open(config, 'w') do |f|
132
+ opts = @options.dup
133
+ opts.delete(:list)
134
+ opts.delete(:section)
135
+ f.puts YAML.dump(opts)
136
+ warn "Config file saved to #{config}"
137
+ end
138
+ end
139
+
115
140
  @theme = load_theme(@options[:theme])
116
- @cols = @options[:width]
141
+ @cols = @options[:width] - 2
117
142
  @output = ''
118
143
  @headers = []
119
144
  @setheaders = []
@@ -122,11 +147,32 @@ module CLIMarkdown
122
147
  @ref_links = {}
123
148
  @footnotes = {}
124
149
 
150
+ renderer = Redcarpet::Render::Console.new
151
+ renderer.theme = @theme
152
+ renderer.cols = @cols
153
+ renderer.log = @log
154
+ renderer.options = @options
155
+
156
+ markdown = Redcarpet::Markdown.new(renderer,
157
+ autolink: true,
158
+ fenced_code_blocks: true,
159
+ footnotes: true,
160
+ hard_wrap: false,
161
+ highlight: true,
162
+ lax_spacing: true,
163
+ quote: false,
164
+ space_after_headers: false,
165
+ strikethrough: true,
166
+ superscript: true,
167
+ tables: true,
168
+ underline: false)
169
+
125
170
  if !args.empty?
126
171
  files = args.delete_if { |f| !File.exist?(f) }
127
172
  files.each do |file|
128
173
  @log.info(%(Processing "#{file}"))
129
174
  @file = file
175
+ renderer.file = @file
130
176
  begin
131
177
  input = IO.read(file).force_encoding('utf-8')
132
178
  rescue StandardError
@@ -137,7 +183,7 @@ module CLIMarkdown
137
183
  puts list_headers(input)
138
184
  Process.exit 0
139
185
  else
140
- convert_markdown(input)
186
+ @output = markdown.render(input)
141
187
  end
142
188
  end
143
189
  printout
@@ -153,14 +199,13 @@ module CLIMarkdown
153
199
  puts list_headers(input)
154
200
  Process.exit 0
155
201
  else
156
- convert_markdown(input)
202
+ @output = markdown.render(input)
157
203
  end
158
204
  printout
159
205
  else
160
206
  warn 'No input'
161
207
  Process.exit 1
162
208
  end
163
-
164
209
  end
165
210
 
166
211
  def color(key)
@@ -182,7 +227,7 @@ module CLIMarkdown
182
227
  end
183
228
  if val.is_a? String
184
229
  val = "x #{val}"
185
- res = val.split(/ /).map { |k| k.to_sym }
230
+ res = val.split(/ /).map(&:to_sym)
186
231
  c(res)
187
232
  else
188
233
  c([:reset])
@@ -194,7 +239,7 @@ module CLIMarkdown
194
239
  @headers = []
195
240
  headers = input.scan(/^((?!#!)(\#{1,6})\s*([^#]+?)(?: #+)?\s*|(\S.+)\n([=-]+))$/i)
196
241
 
197
- headers.each {|h|
242
+ headers.each do |h|
198
243
  hlevel = 6
199
244
  title = nil
200
245
  if h[4] =~ /=+/
@@ -208,209 +253,92 @@ module CLIMarkdown
208
253
  title = h[2]
209
254
  end
210
255
  @headers << [
211
- '#'*hlevel,
256
+ '#' * hlevel,
212
257
  title,
213
258
  h[0]
214
259
  ]
215
- }
260
+ end
216
261
  end
217
262
 
218
263
  @headers
219
264
  end
220
265
 
221
-
222
266
  def list_headers(input)
223
267
  h_adjust = highest_header(input) - 1
224
- input.gsub!(/^(#+)/) do |m|
225
- match = Regexp.last_match
226
- new_level = match[1].length - h_adjust
227
- if new_level > 0
228
- "#" * new_level
229
- else
230
- ''
231
- end
268
+ input.gsub!(/^(#+)/) do
269
+ m = Regexp.last_match
270
+ new_level = m[1].length - h_adjust
271
+ new_level.positive? ? '#' * new_level : ''
232
272
  end
233
273
 
234
274
  @headers = get_headers(input)
235
275
  last_level = 0
236
276
  headers_out = []
237
- @headers.each_with_index do |h,idx|
238
-
277
+ @headers.each_with_index do |h, idx|
239
278
  level = h[0].length - 1
240
279
  title = h[1]
241
280
 
242
- if level - 1 > last_level
243
- level = last_level + 1
244
- end
281
+ level = last_level + 1 if level - 1 > last_level
282
+
245
283
  last_level = level
246
284
 
247
285
  subdoc = case level
248
- when 0
249
- ''
250
- when 1
251
- '- '
252
- when 2
253
- '+ '
254
- when 3
255
- '* '
256
- else
257
- ' '
258
- end
259
- headers_out.push ('%3d: %s' % [idx + 1, c(%i[x black])+"."*level+c(%i[x yellow])+subdoc+title.strip+xc])
286
+ when 0
287
+ ''
288
+ when 1
289
+ '- '
290
+ when 2
291
+ '+ '
292
+ when 3
293
+ '* '
294
+ else
295
+ ' '
296
+ end
297
+ headers_out.push format('%<d>d: %<s>s',
298
+ d: idx + 1,
299
+ s: "#{c(%i[x black])}#{'.' * level}#{c(%i[x yellow])}#{subdoc}#{title.strip}#{xc}")
260
300
  end
261
301
 
262
- return headers_out.join("\n")
302
+ headers_out.join("\n")
263
303
  end
264
304
 
265
305
  def highest_header(input)
266
306
  @headers = get_headers(input)
267
307
  top = 6
268
- @headers.each {|h|
269
- top = h[0].length if h[0].length < top
270
- }
308
+ @headers.each { |h| top = h[0].length if h[0].length < top }
271
309
  top
272
310
  end
273
311
 
274
- def color_table(input)
275
- first = true
276
- input.split(/\n/).map{|line|
277
- if first
278
- if line =~ /^\+-+/
279
- line.gsub!(/^/, color('table border'))
280
- else
281
- first = false
282
- line.gsub!(/\|/, "#{color('table border')}|#{color('table header')}")
283
- end
284
- elsif line.strip =~ /^[|:\- +]+$/
285
- line.gsub!(/^(.*)$/, "#{color('table border')}\\1#{color('table color')}")
286
- line.gsub!(/([:\-+]+)/,"#{color('table divider')}\\1#{color('table border')}")
287
- else
288
- line.gsub!(/\|/, "#{color('table border')}|#{color('table color')}")
289
- end
290
- }.join("\n")
291
- end
292
-
293
- def cleanup_tables(input)
294
-
295
- in_table = false
296
- header_row = false
297
- all_content = []
298
- this_table = []
299
- orig_table = []
300
- input.split(/\n/).each {|line|
301
- if line =~ /(\|.*?)+/ && line !~ /^\s*~/
302
- in_table = true
303
- table_line = line.to_s.uncolor.strip.sub(/^\|?\s*/,'|').gsub(/\s*([\|:])\s*/,'\1')
304
-
305
- if table_line.strip.gsub(/[\|:\- ]/,'') == ''
306
- header_row = true
307
- end
308
- this_table.push(table_line)
309
- orig_table.push(line)
310
- else
311
- if in_table
312
- if this_table.length > 2
313
- # if there's no header row, add one, cleanup requires it
314
- unless header_row
315
- cells = this_table[0].sub(/^\|/,'').scan(/.*?\|/).length
316
- cell_row = '|' + ':-----|'*cells
317
- this_table.insert(1, cell_row)
318
- end
319
-
320
- table = this_table.join("\n").strip
321
-
322
- begin
323
- formatted = MDTableCleanup.new(table)
324
- res = formatted.to_md
325
- res = color_table(res)
326
- rescue
327
- res = orig_table.join("\n")
328
- end
329
- all_content.push(res)
330
- else
331
- all_content.push(orig_table.join("\n"))
332
- end
333
- this_table = []
334
- orig_table = []
335
- end
336
- in_table = false
337
- header_row = false
338
- all_content.push(line)
339
- end
340
- }
341
- all_content.join("\n")
342
- end
343
-
344
312
  def clean_markers(input)
345
- input.gsub!(/^(\e\[[\d;]+m)?[%~] ?/,'\1')
346
- input.gsub!(/^(\e\[[\d;]+m)*>(\e\[[\d;]+m)?( +)/,' \3\1\2')
347
- input.gsub!(/^(\e\[[\d;]+m)*>(\e\[[\d;]+m)?/,'\1\2')
348
- input.gsub!(/(\e\[[\d;]+m)?@@@(\e\[[\d;]+m)?$/,'')
313
+ input.gsub!(/^(\e\[[\d;]+m)?[%~] ?/, '\1')
314
+ input.gsub!(/^(\e\[[\d;]+m)*>(\e\[[\d;]+m)?( +)/, ' \3\1\2')
315
+ input.gsub!(/^(\e\[[\d;]+m)*>(\e\[[\d;]+m)?/, '\1\2')
316
+ input.gsub!(/(\e\[[\d;]+m)?@@@(\e\[[\d;]+m)?$/, '')
349
317
  input
350
318
  end
351
319
 
352
320
  def update_inline_links(input)
353
321
  links = {}
354
322
  counter = 1
355
- input.gsub!(/(?<=\])\((.*?)\)/) do |m|
356
- links[counter] = $1.uncolor
323
+ input.gsub!(/(?<=\])\((.*?)\)/) do
324
+ links[counter] = Regexp.last_match(1).uncolor
357
325
  "[#{counter}]"
358
326
  end
359
327
  end
360
328
 
361
- def find_color(line, nullable = false)
329
+ def find_color(line, nullable: false)
362
330
  return line if line.nil?
331
+
363
332
  colors = line.scan(/\e\[[\d;]+m/)
364
- if colors && colors.size > 0
333
+ if colors.size&.positive?
365
334
  colors[-1]
366
335
  else
367
336
  nullable ? nil : xc
368
337
  end
369
338
  end
370
339
 
371
- def color_link(line, text, url)
372
- [
373
- color('link brackets'),
374
- "[",
375
- color('link text'),
376
- text,
377
- color('link brackets'),
378
- "](",
379
- color('link url'),
380
- url,
381
- color('link brackets'),
382
- ")",
383
- find_color(line)
384
- ].join
385
- end
386
-
387
- def color_image(line, text, url)
388
- text.gsub!(/\e\[0m/,color('image title'))
389
-
390
- [
391
- color('image bang'),
392
- "!",
393
- color('image brackets'),
394
- "[",
395
- color('image title'),
396
- text,
397
- color('image brackets'),
398
- "](",
399
- color('image url'),
400
- url,
401
- color('image brackets'),
402
- ")",
403
- find_color(line)
404
- ].join
405
- end
406
-
407
- def valid_lexer?(language)
408
- lexers = %w(Clipper XBase Cucumber cucumber Gherkin gherkin RobotFramework robotframework abap ada ada95ada2005 ahk antlr-as antlr-actionscript antlr-cpp antlr-csharp antlr-c# antlr-java antlr-objc antlr-perl antlr-python antlr-ruby antlr-rb antlr apacheconf aconf apache applescript as actionscript as3 actionscript3 aspectj aspx-cs aspx-vb asy asymptote autoit Autoit awk gawk mawk nawk basemake bash sh ksh bat bbcode befunge blitzmax bmax boo brainfuck bf bro bugs winbugs openbugs c-objdump c ca65 cbmbas ceylon cfengine3 cf3 cfm cfs cheetah spitfire clojure clj cmake cobol cobolfree coffee-script coffeescript common-lisp cl console control coq cpp c++ cpp-objdump c++-objdumb cxx-objdump croc csharp c# css+django css+jinja css+erb css+ruby css+genshitext css+genshi css+lasso css+mako css+myghty css+php css+smarty css cuda cu cython pyx d-objdump d dart delphi pas pascal objectpascal dg diff udiff django jinja dpatch dtd duel Duel Engine Duel View JBST jbst JsonML+BST dylan-console dylan-repl dylan-lid lid dylan ec ecl elixir ex exs erb erl erlang evoque factor fan fancy fy felix flx fortran fsharp gas genshi kid xml+genshi xml+kid genshitext glsl gnuplot go gooddata-cl gosu groff nroff man groovy gst haml HAML haskell hs haxeml hxml html+cheetah html+spitfire html+django html+jinja html+evoque html+genshi html+kid html+lasso html+mako html+myghty html+php html+smarty html+velocity html http hx haXe hybris hy idl iex ini cfg io ioke ik irc jade JADE jags java jlcon js+cheetah javascript+cheetah js+spitfire javascript+spitfire js+django javascript+django js+jinja javascript+jinja js+erb javascript+erb js+ruby javascript+ruby js+genshitext js+genshi javascript+genshitext javascript+genshi js+lasso javascript+lasso js+mako javascript+mako js+myghty javascript+myghty js+php javascript+php js+smarty javascript+smarty js javascript json jsp julia jl kconfig menuconfig linux-config kernel-config koka kotlin lasso lassoscript lhs literate-haskell lighty lighttpd live-script livescript llvm logos logtalk lua make makefile mf bsdmake mako maql mason matlab matlabsession minid modelica modula2 m2 monkey moocode moon moonscript mscgen msc mupad mxml myghty mysql nasm nemerle newlisp newspeak nginx nimrod nim nsis nsi nsh numpy objdump objective-c++ objectivec++ obj-c++ objc++ objective-c objectivec obj-c objc objective-j objectivej obj-j objj ocaml octave ooc opa openedge abl progress perl pl php php3 php4 php5 plpgsql postgresql postgres postscript pot po pov powershell posh ps1 prolog properties protobuf psql postgresql-console postgres-console puppet py3tb pycon pypylog pypy pytb python py sage python3 py3 qml Qt Meta Language Qt modeling Language racket rkt ragel-c ragel-cpp ragel-d ragel-em ragel-java ragel-objc ragel-ruby ragel-rb ragel raw rb ruby duby rbcon irb rconsole rout rd rebol redcode registry rhtml html+erb html+ruby rst rest restructuredtext rust sass SASS scala scaml SCAML scheme scm scilab scss shell-session smali smalltalk squeak smarty sml snobol sourceslist sources.list sp spec splus s r sql sqlite3 squidconf squid.conf squid ssp stan systemverilog sv tcl tcsh csh tea tex latex text trac-wiki moin treetop ts urbiscript vala vapi vb.net vbnet velocity verilog v vgl vhdl vim xml+cheetah xml+spitfire xml+django xml+jinja xml+erb xml+ruby xml+evoque xml+lasso xml+mako xml+myghty xml+php xml+smarty xml+velocity xml xquery xqy xq xql xqm xslt xtend yaml)
409
- return lexers.include? language.strip
410
- end
411
-
412
- def pad_max(block,eol='')
413
- block.split(/\n/).map { |l|
340
+ def pad_max(block, eol='')
341
+ block.split(/\n/).map do |l|
414
342
  new_code_line = l.gsub(/\t/, ' ')
415
343
  orig_length = new_code_line.size + 8 + eol.size
416
344
  pad_count = [@cols - orig_length, 0].max
@@ -418,539 +346,9 @@ module CLIMarkdown
418
346
  [
419
347
  new_code_line,
420
348
  eol,
421
- ' ' * ([pad_count-1,0].max)
349
+ ' ' * [pad_count - 1, 0].max
422
350
  ].join
423
- }.join("\n")
424
- end
425
-
426
- def hiliteCode(language, codeBlock, leader, first_indent, block)
427
- new_indent = first_indent > 0 ? first_indent + 2 : 0
428
- last_indent = first_indent == 0 ? 7 : 5
429
-
430
- if exec_available('pygmentize') && language && valid_lexer?(language)
431
- lexer = "-l #{language}"
432
- begin
433
- hilite, s = Open3.capture2(%Q{pygmentize -f terminal256 -O style=#{@theme['code_block']['pygments_theme']} #{lexer} 2> /dev/null}, :stdin_data=>codeBlock)
434
- if s.success?
435
-
436
- hilite = xc + hilite.split(/\n/).map{|l|
437
- new_code_line = l.gsub(/\t/, ' ')
438
- new_code_line.sub!(/^#{" "*first_indent}/,'')
439
- [
440
- "> ",
441
- color('code_block marker'),
442
- " "*first_indent,
443
- "#{color('code_block bg')}#{l}"
444
- ].join
445
- }.join("\n").blackout(@theme['code_block']['bg']) + "#{xc}\n"
446
- end
447
- rescue => e
448
- @log.error(e)
449
- hilite = block
450
- end
451
- else
452
- hilite = codeBlock.split(/\n/).map do |line|
453
- new_code_line = line.gsub(/\t/, ' ')
454
- new_code_line.sub!(/^#{" "*first_indent}/,'')
455
- new_code_line.gsub!(/ /, "#{color('code_block color')} ")
456
- [
457
- "> ",
458
- color('code_block marker'),
459
- " "*first_indent,
460
- color('code_block color'),
461
- new_code_line,
462
- xc
463
- ].join
464
- end.join("\n")
465
- end
466
-
467
- [
468
- xc,
469
- "\n",
470
- " "*first_indent,
471
- color('code_block border'),
472
- '--[ ',
473
- color('code_block title'),
474
- leader.chomp,
475
- color('code_block border'),
476
- ' ]',
477
- '-'*(@cols-new_indent-leader.size-2),
478
- xc,
479
- "\n",
480
- hilite.chomp,
481
- "\n",
482
- " "*(new_indent),
483
- color('code_block border'),
484
- '-'*(@cols-new_indent),
485
- xc,
486
- "\n"
487
- ].join
488
- end
489
-
490
- def convert_markdown(input)
491
- ## Replace setex headers with ATX
492
- input.gsub!(/^([^\n]+)\n={3,}\s*$/m, "# \\1\n")
493
- input.gsub!(/^([^\n]+?)\n-{3,}\s*$/m, "## \\1\n")
494
-
495
- @headers = get_headers(input)
496
- input += "\n\n@@@"
497
- # yaml/MMD headers
498
- in_yaml = false
499
- if input.split("\n")[0] =~ /(?i-m)^---[ \t]*?(\n|$)/
500
- @log.info("Found YAML")
501
- # YAML
502
- in_yaml = true
503
- input.sub!(/(?i-m)^---[ \t]*\n([\s\S]*?)\n[\-.]{3}[ \t]*\n/) do |yaml|
504
- m = Regexp.last_match
505
- @log.info("Processing YAML Header")
506
- m[0].split(/\n/).map {|line|
507
- if line =~ /^[\-.]{3}\s*$/
508
- line = color('metadata marker') + "%% " + color('metadata border') + line
509
- else
510
- line.sub!(/^(.*?:)[ \t]+(\S)/, '\1 \2')
511
- line = color('metadata marker') + "%% " + color('metadata color') + line
512
- end
513
- if @cols - line.uncolor.size > 0
514
- line += " "*(@cols-line.uncolor.size)
515
- end
516
- }.join("\n") + "#{xc}\n"
517
- end
518
- end
519
-
520
- if !in_yaml && input.gsub(/\n/,' ') =~ /(?i-m)^\w.+:\s+\S+ /
521
- @log.info("Found MMD Headers")
522
- input.sub!(/(?i-m)^([\S ]+:[\s\S]*?)+(?=\n\n)/) do |mmd|
523
- mmd.split(/\n/).map {|line|
524
- line.sub!(/^(.*?:)[ \t]+(\S)/, '\1 \2')
525
- line = color('metadata marker') + "%% " + color('metadata color') + line
526
- if @cols - line.uncolor.size > 0
527
- line += " "*(@cols - line.uncolor.size)
528
- end
529
- }.join("\n") + " "*@cols + "#{xc}\n"
530
- end
531
-
532
- end
533
-
534
- # Gather reference links
535
- input.gsub!(/^\s{,3}(?<![\e*])\[\b(.+)\b\]: +(.+)/) do |m|
536
- match = Regexp.last_match
537
- @ref_links[match[1]] = match[2]
538
- ''
539
- end
540
-
541
- # Gather footnotes (non-inline)
542
- # TODO: Need to implement option to output links as references
543
- input.gsub!(/^ {,3}(?<!\*)(?:\e\[[\d;]+m)*\[(?:\e\[[\d;]+m)*\^(?:\e\[[\d;]+m)*\b(.+)\b(?:\e\[[\d;]+m)*\]: *(.*?)\n/) do |m|
544
- match = Regexp.last_match
545
- @footnotes[match[1].uncolor] = match[2].uncolor
546
- ''
547
- end
548
-
549
- if @options[:section]
550
- new_content = []
551
- @options[:section].each do |sect|
552
- in_section = false
553
- top_level = 1
554
- input.split(/\n/).each do |graf|
555
- if graf =~ /^(#+) *(.*?)( *#+)?$/
556
- m = Regexp.last_match
557
- level = m[1].length
558
- title = m[2]
559
- if in_section
560
- if level >= top_level
561
- new_content.push(graf)
562
- else
563
- in_section = false
564
- break
565
- end
566
- elsif title.downcase == @headers[sect - 1][1].downcase
567
- in_section = true
568
- top_level = level + 1
569
- new_content.push(graf)
570
- else
571
- next
572
- end
573
- elsif in_section
574
- new_content.push(graf)
575
- end
576
- end
577
- end
578
- input = new_content.join("\n")
579
- end
580
-
581
- # fenced code block parsing
582
- input.gsub!(/(?i-m)(^[ \t]*[`~]{3,})([\s\S]*?)\n([\s\S]*?)\1/m) do
583
- language = nil
584
- m = Regexp.last_match
585
- first_indent = m[1].gsub(/\t/, ' ').match(/^ */)[0].size
586
-
587
- if m[2] && !m[2].strip.empty?
588
- language = m[2].strip.split(/ /)[0]
589
- code_block = pad_max(m[3].to_s, '')
590
- leader = language || 'code'
591
- else
592
- first_line = m[3].to_s.split(/\n/)[0]
593
-
594
- if first_line =~ %r{^\s*#!.*/.+}
595
- shebang = first_line.match(%r{^\s*#!.*/(?:env )?([^/]+)$})
596
- language = shebang[1]
597
- code_block = m[3]
598
- leader = shebang[1] || 'code'
599
- else
600
- code_block = pad_max(m[3].to_s, "#{color('code_block eol')}¬")
601
- leader = language || 'code'
602
- end
603
- end
604
- leader += xc
605
-
606
- hiliteCode(language, code_block, leader, first_indent, m[0])
607
- end
608
-
609
- # h_adjust = highest_header(input) - 1
610
- # input.gsub!(/^(#+)/) do |m|
611
- # match = Regexp.last_match
612
- # "#" * (match[1].length - h_adjust)
613
- # end
614
- #
615
- # Headlines
616
- @headers.each {|h|
617
- input.sub!(/^#{Regexp.escape(h[2])}/m) do |m|
618
- pad = ''
619
- ansi = ''
620
- case h[0].length
621
- when 1
622
- ansi = color('h1 color')
623
- pad = color('h1 pad')
624
- char = @theme['h1']['pad_char'] || "="
625
- pad += h[1].length + 2 > @cols ? char*h[1].length : char*(@cols - (h[1].length + 1))
626
- when 2
627
- ansi = color('h2 color')
628
- pad = color('h2 pad')
629
- char = @theme['h2']['pad_char'] || "-"
630
- pad += h[1].length + 2 > @cols ? char*h[1].length : char*(@cols - (h[1].length + 1))
631
- when 3
632
- ansi = color('h3 color')
633
- when 4
634
- ansi = color('h4 color')
635
- when 5
636
- ansi = color('h5 color')
637
- else
638
- ansi = color('h6 color')
639
- end
640
-
641
- # If we're in iTerm and not paginating, add
642
- # iTerm Marks for navigation on h1-3
643
- if h[0].length < 4 &&
644
- ENV['TERM_PROGRAM'] =~ /^iterm/i &&
645
- @options[:pager] == false
646
- ansi = "\e]1337;SetMark\a" + ansi
647
- end
648
-
649
- "\n#{xc}#{ansi}#{h[1]} #{pad}#{xc}\n"
650
- end
651
- }
652
-
653
- # remove empty links
654
- input.gsub!(/\[(.*?)\]\(\s*?\)/, '\1')
655
- input.gsub!(/\[(.*?)\]\[\]/, '[\1][\1]')
656
-
657
- lines = input.split(/\n/)
658
-
659
- # previous_indent = 0
660
-
661
- lines.map!.with_index do |aLine, i|
662
- line = aLine.dup
663
- clean_line = line.dup.uncolor
664
-
665
-
666
- if clean_line.uncolor =~ /(^[%~])/ # || clean_line.uncolor =~ /^( {4,}|\t+)/
667
- ## TODO: find indented code blocks and prevent highlighting
668
- ## Needs to miss block indented 1 level in lists
669
- ## Needs to catch lists in code
670
- ## Needs to avoid within fenced code blocks
671
- # if line =~ /^([ \t]+)([^*-+]+)/
672
- # indent = $1.gsub(/\t/, " ").size
673
- # if indent >= previous_indent
674
- # line = "~" + line
675
- # end
676
- # p [indent, previous_indent]
677
- # previous_indent = indent
678
- # end
679
- else
680
- # list items
681
- # TODO: Fix ordered list numbering, pad numbers based on total number of list items
682
- line.gsub!(/^(\s*)([*\-+]|\d+\.) /) do |m|
683
- match = Regexp.last_match
684
- last = find_color(match.pre_match)
685
- mcolor = match[2] =~ /^\d+\./ ? 'list number' : 'list bullet'
686
- indent = match[1] || ''
687
- [
688
- indent,
689
- color(mcolor),
690
- match[2], " ",
691
- color('list color')
692
- ].join
693
- end
694
-
695
- # definition lists
696
- line.gsub!(/^(:\s*)(.*?)/) do |m|
697
- match = Regexp.last_match
698
- [
699
- color('dd marker'),
700
- match[1],
701
- " ",
702
- color('dd color'),
703
- match[2],
704
- xc
705
- ].join
706
- end
707
-
708
- # place footnotes under paragraphs that reference them
709
- if line =~ /\[(?:\e\[[\d;]+m)*\^(?:\e\[[\d;]+m)*(\S+)(?:\e\[[\d;]+m)*\]/
710
- match = Regexp.last_match
711
- key = match[1].uncolor
712
- if @footnotes.key? key
713
- line = "#{xc}#{line}"
714
- line += "\n\n#{color('footnote brackets')}[#{color('footnote caret')}^#{color('footnote title')}#{key}#{color('footnote brackets')}]: #{color('footnote note')}#{@footnotes[key]}#{xc}"
715
- @footnotes.delete(key)
716
- end
717
- end
718
-
719
- # color footnote references
720
- line.gsub!(/\[\^(\S+)\]/) do |m|
721
- match = Regexp.last_match
722
- last = find_color(match.pre_match, true)
723
- counter = i
724
- while last.nil? && counter > 0
725
- counter -= 1
726
- find_color(lines[counter])
727
- end
728
- "#{color('footnote brackets')}[#{color('footnote caret')}^#{color('footnote title')}#{match[1]}#{color('footnote brackets')}]" + (last ? last : xc)
729
- end
730
-
731
- # blockquotes
732
- line.gsub!(/^(\s*>)+( .*?)?$/) do |m|
733
- match = Regexp.last_match
734
- last = find_color(match.pre_match, true)
735
- counter = i
736
- while last.nil? && counter > 0
737
- counter -= 1
738
- find_color(lines[counter])
739
- end
740
- "#{c(%i[b black])}#{match[1]}#{c(%i[x magenta])} #{match[2]}" + (last ? last : xc)
741
- end
742
-
743
- # make reference links inline
744
- line.gsub!(/(?<![\e*])\[(\b.*?\b)?\]\[(\b.+?\b)?\]/) do |m|
745
- match = Regexp.last_match
746
- title = match[2] || ''
747
- text = match[1] || ''
748
- if match[2] && @ref_links.key?(title.downcase)
749
- "[#{text}](#{@ref_links[title]})"
750
- elsif match[1] && @ref_links.key?(text.downcase)
751
- "[#{text}](#{@ref_links[text]})"
752
- else
753
- if input.match(/^#+\s*#{Regexp.escape(text)}/i)
754
- "[#{text}](##{text})"
755
- else
756
- match[1]
757
- end
758
- end
759
- end
760
-
761
- # color inline links
762
- line.gsub!(/(?<![\e*!])\[(\S.*?\S)\]\((\S.+?\S)\)/) do |m|
763
- match = Regexp.last_match
764
- color_link(match.pre_match, match[1], match[2])
765
- end
766
-
767
- # horizontal rules
768
- line.gsub!(/^ {,3}([\-*] ?){3,}$/) do |m|
769
- color('hr color') + '_'*@cols + xc
770
- end
771
-
772
- # escaped characters
773
- line.gsub!(/\\(\S)/,'\1')
774
-
775
- # bold, bold/italic
776
- line.gsub!(/(?<pre>^|[ "'\(“])(?<open>[\*_]{2,3})(?<content>[^\*_\s][^\*_]+?[^\*_\s])[\*_]{2,3}/) do |m|
777
- match = Regexp.last_match
778
- last = find_color(match.pre_match, true)
779
- counter = i
780
- while last.nil? && counter > 0
781
- counter -= 1
782
- last = find_color(lines[counter])
783
- end
784
- emph = match['open'].length == 2 ? color('emphasis bold') : color('emphasis bold-italic')
785
- "#{match['pre']}#{emph}#{match['content']}" + (last ? last : xc)
786
- end
787
-
788
- # italic
789
- line.gsub!(/(?<pre>^|[ "'\(“])[\*_](?<content>[^\*_\s][^\*_]+?[^\*_\s])[\*_]/) do |m|
790
- match = Regexp.last_match
791
- last = find_color(match.pre_match, true)
792
- counter = i
793
- while last.nil? && counter > 0
794
- counter -= 1
795
- last = find_color(lines[counter])
796
- end
797
- "#{match['pre']}#{color('emphasis italic')}#{match[2]}" + (last ? last : xc)
798
- end
799
-
800
- # equations
801
- line.gsub!(/((\\\\\[|\$\$)(.*?)(\\\\\]|\$\$)|(\\\\\(|\$)(.*?)(\\\\\)|\$))/) do |m|
802
- match = Regexp.last_match
803
- last = find_color(match.pre_match)
804
- if match[2]
805
- brackets = [match[2], match[4]]
806
- equat = match[3]
807
- else
808
- brackets = [match[5], match[7]]
809
- equat = match[6]
810
- end
811
- "#{c(%i[b black])}#{brackets[0]}#{xc}#{c(%i[b blue])}#{equat}#{c(%i[b black])}#{brackets[1]}" + (last ? last : xc)
812
- end
813
-
814
- # misc html
815
- line.gsub!(%r{<br/?>}, "\n")
816
- line.gsub!(%r{(?i-m)((</?)(\w+[\s\S]*?)(>))}) do
817
- match = Regexp.last_match
818
- last = find_color(match.pre_match)
819
- [
820
- color('html brackets'),
821
- match[2],
822
- color('html color'),
823
- match[3],
824
- color('html brackets'),
825
- match[4],
826
- last || xc
827
- ].join
828
- end
829
-
830
- # inline code spans
831
- line.gsub!(/`(.*?)`/) do
832
- match = Regexp.last_match
833
- last = find_color(match.pre_match, true)
834
- [
835
- color('code_span marker'),
836
- '`',
837
- color('code_span color'),
838
- match[1],
839
- color('code_span marker'),
840
- '`',
841
- last || xc
842
- ].join
843
- end
844
- end
845
-
846
- ## Should force a foreground color but doesn't...
847
- # unless line =~ /^\s*\e\[[\d;]+m/
848
- # line.sub!(/^(\s*)/, "\\1#{color('text')}")
849
- # end
850
-
851
- line
852
- end
853
-
854
- input = lines.join("\n")
855
-
856
- # images
857
- input.gsub!(/^(.*?)!\[(.*)?\]\((.*?\.(?:png|gif|jpg))( +.*)?\)/) do
858
- match = Regexp.last_match
859
- if match[1].uncolor =~ /^( {4,}|\t)+/
860
- match[0]
861
- else
862
- tail = match[4].nil? ? '' : " "+match[4].strip
863
- result = nil
864
- if (exec_available('imgcat') || exec_available('chafa')) && @options[:local_images]
865
- if match[3]
866
- img_path = match[3]
867
- if img_path =~ /^http/ && @options[:remote_images]
868
-
869
- if exec_available('chafa')
870
- if File.directory?('.mdless_tmp')
871
- FileUtils.rm_r '.mdless_tmp', force: true
872
- end
873
- Dir.mkdir('.mdless_tmp')
874
- Dir.chdir('.mdless_tmp')
875
- `curl -SsO #{img_path} 2> /dev/null`
876
- tmp_img = File.basename(img_path)
877
- img = `chafa "#{tmp_img}"`
878
- pre = match[2].size > 0 ? " #{c(%i[d blue])}[#{match[2].strip}]\n" : ''
879
- post = tail.size > 0 ? "\n #{c(%i[b blue])}-- #{tail} --" : ''
880
- result = pre + img + post
881
- Dir.chdir('..')
882
- FileUtils.rm_r '.mdless_tmp', force: true
883
- else
884
- if exec_available('imgcat')
885
- begin
886
- res, s = Open3.capture2(%Q{curl -sS "#{img_path}" 2> /dev/null | imgcat})
887
-
888
- if s.success?
889
- pre = match[2].size > 0 ? " #{c(%i[d blue])}[#{match[2].strip}]\n" : ''
890
- post = tail.size > 0 ? "\n #{c(%i[b blue])}-- #{tail} --" : ''
891
- result = pre + res + post
892
- end
893
- rescue => e
894
- @log.error(e)
895
- end
896
- else
897
- @log.warn('No viewer for remote images')
898
- end
899
- end
900
- else
901
- if img_path =~ %r{^[~/]}
902
- img_path = File.expand_path(img_path)
903
- elsif @file
904
- base = File.expand_path(File.dirname(@file))
905
- img_path = File.join(base, img_path)
906
- end
907
- if File.exist?(img_path)
908
- pre = !match[2].empty? ? " #{c(%i[d blue])}[#{match[2].strip}]\n" : ''
909
- post = !tail.empty? ? "\n #{c(%i[b blue])}-- #{tail} --" : ''
910
- if exec_available('chafa')
911
- img = `chafa "#{img_path}"`
912
- elsif exec_available('imgcat')
913
- img = `imgcat "#{img_path}"`
914
- end
915
- result = pre + img + post
916
- end
917
- end
918
- end
919
- end
920
- if result.nil?
921
- match[1] + color_image(match.pre_match, match[2], match[3] + tail) + xc
922
- else
923
- match[1] + result + xc
924
- end
925
- end
926
- end
927
-
928
- @footnotes.each do |t, v|
929
- input += [
930
- "\n\n",
931
- color('footnote brackets'),
932
- '[',
933
- color('footnote caret'),
934
- '^',
935
- color('footnote title'),
936
- t,
937
- color('footnote brackets'),
938
- ']: ',
939
- color('footnote note'),
940
- v,
941
- xc
942
- ].join
943
- end
944
-
945
- @output += input
946
- end
947
-
948
- def exec_available(cli)
949
- if File.exist?(File.expand_path(cli))
950
- File.executable?(File.expand_path(cli))
951
- else
952
- system "which #{cli}", out: File::NULL, err: File::NULL
953
- end
351
+ end.join("\n")
954
352
  end
955
353
 
956
354
  def page(text, &callback)
@@ -989,40 +387,37 @@ module CLIMarkdown
989
387
  end
990
388
 
991
389
  def printout
992
- out = @output.rstrip.split(/\n/).map {|p|
390
+ out = @output.rstrip.split(/\n/).map do |p|
993
391
  p.wrap(@cols, color('text'))
994
- }.join("\n")
995
-
392
+ end.join("\n")
996
393
 
997
- unless out && out.size > 0
998
- @log.warn "No results"
394
+ unless out.size&.positive?
395
+ @log.warn 'No results'
999
396
  Process.exit
1000
397
  end
1001
398
 
1002
- out = cleanup_tables(out)
1003
399
  out = clean_markers(out)
1004
- out = out.gsub(/\n{2,}/m,"\n\n") + "#{xc}"
400
+ out = "#{out.gsub(/\n{2,}/m, "\n\n")}#{xc}"
1005
401
 
1006
- unless @options[:color]
1007
- out.uncolor!
1008
- end
402
+ out.uncolor! unless @options[:color]
1009
403
 
1010
404
  if @options[:pager]
1011
405
  page(out)
1012
406
  else
1013
- $stdout.print (out.rstrip)
407
+ $stdout.print out.rstrip
1014
408
  end
1015
409
  end
1016
410
 
1017
411
  def which_pager
1018
- pagers = [ENV['PAGER'], ENV['GIT_PAGER']]
412
+ # pagers = [ENV['PAGER'], ENV['GIT_PAGER']]
413
+ pagers = [ENV['PAGER']]
1019
414
 
1020
- if exec_available('git')
1021
- git_pager = `git config --get-all core.pager || true`.split.first
1022
- git_pager && pagers.push(git_pager)
1023
- end
415
+ # if exec_available('git')
416
+ # git_pager = `git config --get-all core.pager || true`.split.first
417
+ # git_pager && pagers.push(git_pager)
418
+ # end
1024
419
 
1025
- pagers.concat(['bat', 'less', 'more', 'cat', 'pager'])
420
+ pagers.concat(['less', 'more', 'cat', 'pager'])
1026
421
 
1027
422
  pagers.select! do |f|
1028
423
  if f
@@ -1032,7 +427,7 @@ module CLIMarkdown
1032
427
  @log.warn('most not allowed as pager')
1033
428
  false
1034
429
  else
1035
- system "which #{f}", :out => File::NULL, :err => File::NULL
430
+ system "which #{f}", out: File::NULL, err: File::NULL
1036
431
  end
1037
432
  else
1038
433
  false
@@ -1041,21 +436,25 @@ module CLIMarkdown
1041
436
 
1042
437
  pg = pagers.first
1043
438
  args = case pg
1044
- when 'delta'
1045
- ' --pager="less -Xr"'
1046
- when 'less'
1047
- ' -Xr'
1048
- when 'bat'
1049
- ' -p --pager="less -Xr"'
1050
- else
1051
- ''
1052
- end
439
+ # when 'delta'
440
+ # ' --pager="less -Xr"'
441
+ when 'less'
442
+ ' -Xr'
443
+ # when 'bat'
444
+ # ' -p --pager="less -Xr"'
445
+ else
446
+ ''
447
+ end
1053
448
 
1054
449
  [pg, args]
1055
450
  end
1056
451
 
1057
- def xc
1058
- color('text')
452
+ def exec_available(cli)
453
+ if File.exist?(File.expand_path(cli))
454
+ File.executable?(File.expand_path(cli))
455
+ else
456
+ system "which #{cli}", out: File::NULL, err: File::NULL
457
+ end
1059
458
  end
1060
459
  end
1061
460
  end
data/lib/mdless/tables.rb CHANGED
@@ -1,16 +1,15 @@
1
1
  module CLIMarkdown
2
2
  class MDTableCleanup
3
-
4
- PAD_CHAR = '⎕'
3
+ PAD_CHAR = "\u00A0"
5
4
 
6
5
  def initialize(input)
7
6
  @string = input
8
- @format_row = []
9
7
  end
10
8
 
11
9
  def parse
10
+ @format_row = []
12
11
  @table = []
13
- format = []
12
+ fmt = []
14
13
  cols = 0
15
14
  rows = @string.split(/\r?\n/)
16
15
  rows.each do |row|
@@ -19,29 +18,29 @@ module CLIMarkdown
19
18
  row_array = row.split(/\|/)
20
19
  row_array.map! { |cell| cell.strip }
21
20
  if row =~ /^[\|:\- ]+$/
22
- format = row_array
21
+ fmt = row_array
23
22
  else
24
23
  @table.push row_array
25
24
  end
26
25
  cols = row_array.length if row_array.length > cols
27
26
  end
28
27
 
29
- format.each_with_index {|cell, i|
28
+ fmt.each_with_index do |cell, i|
30
29
  cell.strip!
31
- f = 'left'
32
- if cell =~ /^:.*?:$/
33
- f = 'center'
34
- elsif cell =~ /[^:]+:$/
35
- f = 'right'
30
+ f = case cell
31
+ when /^:.*?:$/
32
+ :center
33
+ when /[^:]+:$/
34
+ :right
36
35
  else
37
- f = 'just'
36
+ :just
38
37
  end
39
38
  @format_row.push(f)
40
- }
39
+ end
41
40
 
42
41
  if @format_row.length < cols
43
42
  (cols - @format_row.length).times do
44
- @format_row.push('left')
43
+ @format_row.push(:left)
45
44
  end
46
45
  end
47
46
 
@@ -60,9 +59,9 @@ module CLIMarkdown
60
59
  @table ||= parse
61
60
  end
62
61
 
63
- def column_width(i)
62
+ def column_width(idx)
64
63
  @widths ||= column_widths
65
- @widths[i]
64
+ @widths[idx]
66
65
  end
67
66
 
68
67
  def column_widths
@@ -72,7 +71,7 @@ module CLIMarkdown
72
71
  end
73
72
 
74
73
  table.each do |row|
75
- @format_row.each_with_index do |cell, i|
74
+ @format_row.each_with_index do |_, i|
76
75
  length = row[i].strip.length
77
76
  @widths[i] = length if length > @widths[i]
78
77
  end
@@ -81,32 +80,31 @@ module CLIMarkdown
81
80
  @widths
82
81
  end
83
82
 
84
- def pad(string,type,length)
85
- string.strip!
86
- if type == 'center'
87
- string.center(length, PAD_CHAR)
88
- elsif type == 'right'
89
- string.rjust(length, PAD_CHAR)
90
- elsif type == 'left'
91
- string.ljust(length, PAD_CHAR)
83
+ def pad(string, alignment, length)
84
+ case alignment
85
+ when :center
86
+ string.strip.center(length, PAD_CHAR)
87
+ when :right
88
+ string.strip.rjust(length, PAD_CHAR)
89
+ when :left
90
+ string.strip.ljust(length, PAD_CHAR)
92
91
  else
93
- string.ljust(length, PAD_CHAR)
92
+ string.strip.ljust(length, PAD_CHAR)
94
93
  end
95
94
  end
96
95
 
97
96
  def separator(length, alignment)
98
- out = "".ljust(length,'-')
97
+ out = ''.ljust(length, '-')
99
98
  case alignment
100
- when 'left'
101
- out = ':' + out + '-'
102
- when 'right'
103
- out = '-' + out + ':'
104
- when 'center'
105
- out = ":#{out}:"
99
+ when :left
100
+ ":#{out}-"
101
+ when :right
102
+ "-#{out}:"
103
+ when :center
104
+ ":#{out}:"
106
105
  else
107
- out = "-#{out}-"
106
+ "-#{out}-"
108
107
  end
109
- out
110
108
  end
111
109
 
112
110
  def header_separator_row
@@ -128,18 +126,14 @@ module CLIMarkdown
128
126
  def to_md
129
127
  output = []
130
128
  t = table.clone
131
-
132
- t.each_with_index do |row, index|
133
- row.map!.with_index { |cell, i| cell = pad(cell, @format_row[i], column_width(i)) }
134
- output.push("| #{row.join(' | ').lstrip} |")
129
+ t.each do |row|
130
+ new_row = row.map.with_index { |cell, i| pad(cell, @format_row[i], column_width(i)) }.join(' | ')
131
+ output.push("| #{new_row} |")
135
132
  end
136
133
  output.insert(1, header_separator_row)
137
134
  output.insert(0, table_border)
138
135
  output.push(table_border)
139
-
140
- output.join("\n").gsub(/((?<=\| )#{PAD_CHAR}+|#{PAD_CHAR}+(?= \|))/) {|m|
141
- " "*m.length
142
- }
136
+ output.join("\n")
143
137
  end
144
138
  end
145
139
  end
data/lib/mdless/theme.rb CHANGED
@@ -70,6 +70,7 @@ module CLIMarkdown
70
70
  'pygments_theme' => 'monokai'
71
71
  },
72
72
  'dd' => {
73
+ 'term' => 'black on_white',
73
74
  'marker' => 'd red',
74
75
  'color' => 'b white'
75
76
  },
@@ -86,7 +87,9 @@ module CLIMarkdown
86
87
  'html' => {
87
88
  'brackets' => 'd yellow on_black',
88
89
  'color' => 'yellow on_black'
89
- }
90
+ },
91
+ 'super' => 'b green',
92
+ 'text' => 'white'
90
93
  }
91
94
 
92
95
  def load_theme_file(theme_file)
@@ -1,3 +1,3 @@
1
1
  module CLIMarkdown
2
- VERSION = '1.0.37'
2
+ VERSION = '2.0.1'
3
3
  end
data/lib/mdless.rb CHANGED
@@ -3,11 +3,14 @@ require 'shellwords'
3
3
  require 'open3'
4
4
  require 'fileutils'
5
5
  require 'logger'
6
+ require 'tty-which'
6
7
  require 'mdless/version.rb'
7
8
  require 'mdless/colors'
8
9
  require 'mdless/tables'
9
10
  require 'mdless/hash'
10
11
  require 'mdless/theme'
12
+ require 'redcarpet'
13
+ require 'mdless/console'
11
14
  require 'mdless/converter'
12
15
 
13
16
  module CLIMarkdown
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mdless
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.37
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-22 00:00:00.000000000 Z
11
+ date: 2023-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redcarpet
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: tty-which
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.5'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: rake
15
43
  requirement: !ruby/object:Gem::Requirement