kramdown 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTERS +10 -1
  3. data/VERSION +1 -1
  4. data/bin/kramdown +15 -12
  5. data/lib/kramdown/converter/base.rb +2 -2
  6. data/lib/kramdown/converter/html.rb +22 -14
  7. data/lib/kramdown/converter/kramdown.rb +25 -20
  8. data/lib/kramdown/converter/latex.rb +11 -10
  9. data/lib/kramdown/converter/man.rb +3 -3
  10. data/lib/kramdown/converter/math_engine/mathjax.rb +1 -1
  11. data/lib/kramdown/converter/remove_html_tags.rb +5 -4
  12. data/lib/kramdown/document.rb +1 -1
  13. data/lib/kramdown/element.rb +1 -1
  14. data/lib/kramdown/options.rb +43 -15
  15. data/lib/kramdown/parser/base.rb +6 -0
  16. data/lib/kramdown/parser/html.rb +24 -18
  17. data/lib/kramdown/parser/kramdown/abbreviation.rb +4 -2
  18. data/lib/kramdown/parser/kramdown/codespan.rb +1 -1
  19. data/lib/kramdown/parser/kramdown/emphasis.rb +6 -1
  20. data/lib/kramdown/parser/kramdown/escaped_chars.rb +1 -1
  21. data/lib/kramdown/parser/kramdown/extensions.rb +6 -6
  22. data/lib/kramdown/parser/kramdown/html.rb +26 -23
  23. data/lib/kramdown/parser/kramdown/html_entity.rb +1 -1
  24. data/lib/kramdown/parser/kramdown/link.rb +4 -4
  25. data/lib/kramdown/parser/kramdown/list.rb +19 -18
  26. data/lib/kramdown/parser/kramdown/smart_quotes.rb +1 -1
  27. data/lib/kramdown/parser/kramdown.rb +5 -4
  28. data/lib/kramdown/utils/entities.rb +661 -5
  29. data/lib/kramdown/utils/html.rb +1 -1
  30. data/lib/kramdown/utils/unidecoder.rb +9 -13
  31. data/lib/kramdown/version.rb +1 -1
  32. data/man/man1/kramdown.1 +18 -0
  33. data/test/test_files.rb +8 -0
  34. data/test/testcases/block/04_header/with_header_links.html +7 -0
  35. data/test/testcases/block/04_header/with_header_links.options +2 -0
  36. data/test/testcases/block/04_header/with_header_links.text +8 -0
  37. data/test/testcases/block/04_header/with_line_break.html +1 -0
  38. data/test/testcases/block/04_header/with_line_break.text +1 -0
  39. data/test/testcases/block/08_list/escaping.html +4 -0
  40. data/test/testcases/block/08_list/escaping.text +4 -0
  41. data/test/testcases/block/08_list/nested_compact.kramdown +7 -0
  42. data/test/testcases/block/08_list/nested_compact.text +6 -0
  43. data/test/testcases/block/08_list/special_cases.html +10 -0
  44. data/test/testcases/block/08_list/special_cases.text +9 -0
  45. data/test/testcases/block/09_html/cdata_section.html +10 -0
  46. data/test/testcases/block/09_html/cdata_section.text +10 -0
  47. data/test/testcases/block/09_html/html_to_native/table_simple.html +3 -0
  48. data/test/testcases/block/09_html/html_to_native/table_simple.text +3 -0
  49. data/test/testcases/block/12_extension/options.html +2 -2
  50. data/test/testcases/block/12_extension/options2.html +2 -2
  51. data/test/testcases/block/14_table/table_with_footnote.html +2 -2
  52. data/test/testcases/block/16_toc/toc_with_footnotes.html +2 -2
  53. data/test/testcases/span/02_emphasis/normal.html +6 -1
  54. data/test/testcases/span/02_emphasis/normal.text +5 -0
  55. data/test/testcases/span/04_footnote/backlink_inline.html +10 -10
  56. data/test/testcases/span/04_footnote/backlink_text.html +2 -2
  57. data/test/testcases/span/04_footnote/footnote_link_text.html +12 -0
  58. data/test/testcases/span/04_footnote/footnote_link_text.options +1 -0
  59. data/test/testcases/span/04_footnote/footnote_link_text.text +4 -0
  60. data/test/testcases/span/04_footnote/footnote_nr.html +3 -3
  61. data/test/testcases/span/04_footnote/footnote_prefix.html +3 -3
  62. data/test/testcases/span/04_footnote/inside_footnote.html +6 -6
  63. data/test/testcases/span/04_footnote/markers.html +10 -10
  64. data/test/testcases/span/04_footnote/placement.html +2 -2
  65. data/test/testcases/span/04_footnote/regexp_problem.html +2 -2
  66. data/test/testcases/span/04_footnote/without_backlink.html +2 -2
  67. data/test/testcases/span/abbreviations/abbrev.html +4 -0
  68. data/test/testcases/span/abbreviations/abbrev.text +7 -0
  69. data/test/testcases/span/abbreviations/in_footnote.html +2 -2
  70. metadata +21 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c41b216fbd6f50c68b10864bc3a98040f79641db9af8ced05eb43f7817335ad
4
- data.tar.gz: ef3adb19cbfbe4586bf0ef4f14362ca843a7fe3331ff6dc990c270ff65cff000
3
+ metadata.gz: 53bf662f86052a77c6c9867b0c4e6808c9cee58ce1ed2b5e77c74b9d015b8e73
4
+ data.tar.gz: 3f56c0fd6fb00b867ade3ce1df9ddda4380aa01307b37420fbc5a4f1330a8156
5
5
  SHA512:
6
- metadata.gz: 483e269f858aadd6bf8e7bf2f49ec90ddfdcd9628aec17822eb7eefcfc21897eb19d258a84b6291611a38a5958a79013c2c656d35f7740b116923bd8624a2329
7
- data.tar.gz: 5ffeef35cdfb994411414d62bd8b5fcf09fcea7d926069896248148575b88b4abbfdc1e5aab6da8dbe6f97c3e0a4921b391802e391ea3c76a646be7f64fbbbda
6
+ metadata.gz: 813301a1fe55b9eeb724fec2e482a694e74852d2509cd74e64cbc5f5df5122f77d63b317439c4184b9ebc7651584d5c777d58eb29183e07ab941d453c12a6ed4
7
+ data.tar.gz: 610257c36fc35ac7195114f1a5458d02939116696e799ab257a821a2ab5025ecf94470a4800cd767dfdc0730da0a0ec599276ac2ac745ef64b07d2bc4d20ba9b
data/CONTRIBUTERS CHANGED
@@ -1,6 +1,6 @@
1
1
  Count Name
2
2
  ======= ====
3
- 964 Thomas Leitner <t_leitner@gmx.at>
3
+ 986 Thomas Leitner <t_leitner@gmx.at>
4
4
  18 Ashwin Maroli <ashmaroli@gmail.com>
5
5
  7 Christian Cornelssen <ccorn@1tein.de>
6
6
  6 Gioele Barabucci <gioele@svario.it>
@@ -21,9 +21,11 @@
21
21
  2 Nathanael Jones <nathanael.jones@gmail.com>
22
22
  2 Max Meyer <dev@fedux.org>
23
23
  2 Jo Hund <jhund@clearcove.ca>
24
+ 2 Bryce Willey <Bryce.Steven.Willey@gmail.com>
24
25
  2 Bran <m.versum@gmail.com>
25
26
  1 winniehell <git@winniehell.de>
26
27
  1 William <suttonwilliamd@gmail.com>
28
+ 1 Virgil Ierubino <30758921+Convincible@users.noreply.github.com>
27
29
  1 Uwe Kubosch <donv@users.noreply.github.com>
28
30
  1 utenmiki <utenmiki@gmail.com>
29
31
  1 Trevor Wennblom <trevor@well.com>
@@ -45,6 +47,8 @@
45
47
  1 scherr <maximilianscherr@gmail.com>
46
48
  1 Postmodern <postmodern.mod3@gmail.com>
47
49
  1 Pete Michaud <michaudp@gmail.com>
50
+ 1 Paul McMahon <paul@tokyodev.com>
51
+ 1 Paul <2528280+psfrolov@users.noreply.github.com>
48
52
  1 Noah Doersing <doersino@gmail.com>
49
53
  1 myqlarson <myqlarson@gmail.com>
50
54
  1 milo.simpson <milo.simpson@bazaarvoice.com>
@@ -59,9 +63,11 @@
59
63
  1 Kir Kolyshkin <kolyshkin@gmail.com>
60
64
  1 Jun Aruga <jaruga@redhat.com>
61
65
  1 Jonathan Hooper <jonathan.hooper@gsa.gov>
66
+ 1 John Haugeland <stonecypher@gmail.com>
62
67
  1 John Croisant <jacius@gmail.com>
63
68
  1 Joe Fiorini <joe@faithfulgeek.org>
64
69
  1 Jens Kraemer <jk@jkraemer.net>
70
+ 1 Jay Stramel <js@ionactual.com>
65
71
  1 Hirofumi Wakasugi <baenej@gmail.com>
66
72
  1 Hector Correa <hector@hectorcorrea.com>
67
73
  1 Florian Klampfer <f.klampfer@gmail.com>
@@ -72,13 +78,16 @@
72
78
  1 Daniel Bair <daniel@danielbair.com>
73
79
  1 Damien Pollet <damien.pollet@gmail.com>
74
80
  1 Christopher Jefferson <caj21@st-andrews.ac.uk>
81
+ 1 Christian Boos <christian.boos@bct-technology.com>
75
82
  1 Cédric Boutillier <cedric.boutillier@gmail.com>
76
83
  1 Bob Lail <lail@squareup.com>
84
+ 1 Ashesh Kumar Singh <user501254@gmail.com>
77
85
  1 Ashe Connor <ashe@kivikakk.ee>
78
86
  1 aschmitz <29508+aschmitz@users.noreply.github.com>
79
87
  1 Antoine Cotten <hello@acotten.com>
80
88
  1 Andrew <andrew.dale.wylie@gmail.com>
81
89
  1 Alpha Chen <alpha.chen@gmail.com>
82
90
  1 Alex Tomlins <alex.tomlins@digital.cabinet-office.gov.uk>
91
+ 1 Alex Taylor <alex@alextaylor.ca>
83
92
  1 Alexey Vasiliev <le0pard@users.noreply.github.com>
84
93
  1 284km <k.furuhashi10@gmail.com>
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.4.0
1
+ 2.5.0
data/bin/kramdown CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- # -*- coding: utf-8 -*-
2
+ # -*- coding: utf-8; frozen_string_literal: true -*-
3
3
  #
4
4
  #--
5
5
  # Copyright (C) 2009-2019 Thomas Leitner <t_leitner@gmx.at>
@@ -36,7 +36,7 @@ def add_kramdown_options(opts, parsed_options, banner: [], ignore: [])
36
36
  opts.on("--#{no} ARG", type) {|v| parsed_options[n] = Kramdown::Options.parse(n, v) }
37
37
  end
38
38
 
39
- definition.desc.split(/\n/).each do |line|
39
+ definition.desc.split("\n").each do |line|
40
40
  opts.separator opts.summary_indent + ' ' * 6 + line
41
41
  end
42
42
  opts.separator ''
@@ -78,14 +78,12 @@ OptionParser.new do |opts|
78
78
  "prefix) separated", "by commas (e.g. parser-gfm,syntax-coderay)",
79
79
  "Note: Use this option before other options!") do |exts|
80
80
  exts.each do |ext|
81
- begin
82
- require "kramdown-#{ext}"
83
- new_options = add_kramdown_options(opts, options, banner: ["#{ext} options:"],
84
- ignore: defined_options)
85
- defined_options.concat(new_options)
86
- rescue LoadError
87
- $stderr.puts "Couldn't load extension #{ext}, ignoring"
88
- end
81
+ require "kramdown-#{ext}"
82
+ new_options = add_kramdown_options(opts, options, banner: ["#{ext} options:"],
83
+ ignore: defined_options)
84
+ defined_options.concat(new_options)
85
+ rescue LoadError
86
+ $stderr.puts "Couldn't load extension #{ext}, ignoring"
89
87
  end
90
88
  end
91
89
  opts.separator ""
@@ -101,7 +99,7 @@ OptionParser.new do |opts|
101
99
  exit
102
100
  end
103
101
  opts.on("-h", "--help", "Show the help") do
104
- puts opts.summarize('', 5, 72)
102
+ puts opts.summarize(+'', 5, 72)
105
103
  exit
106
104
  end
107
105
 
@@ -111,7 +109,12 @@ end.parse!
111
109
 
112
110
  begin
113
111
  if config_file && File.exist?(config_file)
114
- config_file_options = YAML.safe_load(File.read(config_file), [Symbol])
112
+ config_file_options =
113
+ if YAML.method(:safe_load).parameters.include?(%i[key permitted_classes])
114
+ YAML.safe_load(File.read(config_file), permitted_classes: [Symbol])
115
+ else # compatibility with Psych < 3.1.0
116
+ YAML.safe_load(File.read(config_file), [Symbol])
117
+ end
115
118
  case config_file_options
116
119
  when nil # empty configuration file except perhaps YAML header and comments
117
120
  # Nothing to do
@@ -137,7 +137,7 @@ module Kramdown
137
137
 
138
138
  # Return the template specified by +template+.
139
139
  def self.get_template(template) # :nodoc:
140
- format_ext = '.' + ::Kramdown::Utils.snake_case(self.name.split(/::/).last)
140
+ format_ext = '.' + ::Kramdown::Utils.snake_case(name.split("::").last)
141
141
  shipped = File.join(::Kramdown.data_dir, template + format_ext)
142
142
  if File.exist?(template)
143
143
  File.read(template)
@@ -146,7 +146,7 @@ module Kramdown
146
146
  elsif File.exist?(shipped)
147
147
  File.read(shipped)
148
148
  elsif template.start_with?('string://')
149
- template.sub(/\Astring:\/\//, '')
149
+ template.delete_prefix("string://")
150
150
  else
151
151
  raise "The specified template file #{template} does not exist"
152
152
  end
@@ -100,8 +100,12 @@ module Kramdown
100
100
  figure_attr = el.attr.dup
101
101
  image_attr = el.children.first.attr.dup
102
102
 
103
- figure_attr['class'] = image_attr.delete('class') if image_attr.key?('class') and not figure_attr.key?('class')
104
- figure_attr['id'] = image_attr.delete('id') if image_attr.key?('id') and not figure_attr.key?('id')
103
+ if image_attr.key?('class') && !figure_attr.key?('class')
104
+ figure_attr['class'] = image_attr.delete('class')
105
+ end
106
+ if image_attr.key?('id') && !figure_attr.key?('id')
107
+ figure_attr['id'] = image_attr.delete('id')
108
+ end
105
109
 
106
110
  body = "#{' ' * (indent + @indent)}<img#{html_attributes(image_attr)} />\n" \
107
111
  "#{' ' * (indent + @indent)}<figcaption>#{image_attr['alt']}</figcaption>\n"
@@ -128,7 +132,7 @@ module Kramdown
128
132
  when "\t" then "<span class=\"ws-tab#{suffix}\">\t</span>"
129
133
  when " " then "<span class=\"ws-space#{suffix}\">&#8901;</span>"
130
134
  end
131
- end.join('')
135
+ end.join
132
136
  end
133
137
  end
134
138
  code_attr = {}
@@ -147,6 +151,13 @@ module Kramdown
147
151
  if @options[:auto_ids] && !attr['id']
148
152
  attr['id'] = generate_id(el.options[:raw_text])
149
153
  end
154
+
155
+ if @options[:header_links] && attr['id'].to_s.length > 0
156
+ link = Element.new(:a, nil, nil)
157
+ link.attr['href'] = "##{attr['id']}"
158
+ el.children.unshift(link)
159
+ end
160
+
150
161
  @toc << [el.options[:level], attr['id'], el.children] if attr['id'] && in_toc?(el)
151
162
  level = output_header_level(el.options[:level])
152
163
  format_as_block_html("h#{level}", attr, inner(el, indent), indent)
@@ -179,7 +190,7 @@ module Kramdown
179
190
  output = ' ' * indent << "<#{el.type}" << html_attributes(el.attr) << ">"
180
191
  res = inner(el, indent)
181
192
  if el.children.empty? || (el.children.first.type == :p && el.children.first.options[:transparent])
182
- output << res << (res =~ /\n\Z/ ? ' ' * indent : '')
193
+ output << res << (res.match?(/\n\Z/) ? ' ' * indent : '')
183
194
  else
184
195
  output << "\n" << res << ' ' * indent
185
196
  end
@@ -303,9 +314,10 @@ module Kramdown
303
314
  @footnotes << [name, el.value, number, 0]
304
315
  @footnotes_by_name[name] = @footnotes.last
305
316
  end
306
- "<sup id=\"fnref:#{name}#{repeat}\" role=\"doc-noteref\">" \
307
- "<a href=\"#fn:#{name}\" class=\"footnote\" rel=\"footnote\">" \
308
- "#{number}</a></sup>"
317
+ formatted_link_text = sprintf(@options[:footnote_link_text], number)
318
+ "<sup id=\"fnref:#{name}#{repeat}\">" \
319
+ "<a href=\"#fn:#{name}\" class=\"footnote\" rel=\"footnote\" role=\"doc-noteref\">" \
320
+ "#{formatted_link_text}</a></sup>"
309
321
  end
310
322
 
311
323
  def convert_raw(el, _indent)
@@ -340,7 +352,7 @@ module Kramdown
340
352
  if (result = @options[:typographic_symbols][el.value])
341
353
  escape_html(result, :text)
342
354
  else
343
- TYPOGRAPHIC_SYMS[el.value].map {|e| entity_to_str(e) }.join('')
355
+ TYPOGRAPHIC_SYMS[el.value].map {|e| entity_to_str(e) }.join
344
356
  end
345
357
  end
346
358
 
@@ -378,11 +390,7 @@ module Kramdown
378
390
  end
379
391
  if @toc_code
380
392
  toc_tree = generate_toc_tree(@toc, @toc_code[0], @toc_code[1] || {})
381
- text = if !toc_tree.children.empty?
382
- convert(toc_tree, 0)
383
- else
384
- ''
385
- end
393
+ text = toc_tree.children.empty? ? '' : convert(toc_tree, 0)
386
394
  result.sub!(/#{@toc_code.last}/, text.gsub(/\\/, "\\\\\\\\"))
387
395
  end
388
396
  result
@@ -492,7 +500,7 @@ module Kramdown
492
500
  backlink_text = escape_html(@options[:footnote_backlink], :text)
493
501
  while i < @footnotes.length
494
502
  name, data, _, repeat = *@footnotes[i]
495
- li = Element.new(:li, nil, 'id' => "fn:#{name}", 'role' => 'doc-endnote')
503
+ li = Element.new(:li, nil, 'id' => "fn:#{name}")
496
504
  li.children = Marshal.load(Marshal.dump(data.children))
497
505
 
498
506
  para = nil
@@ -45,7 +45,8 @@ module Kramdown
45
45
  elsif el.block? &&
46
46
  ![:li, :dd, :dt, :td, :th, :tr, :thead, :tbody, :tfoot, :blank].include?(el.type) &&
47
47
  (el.type != :html_element || @stack.last.type != :html_element) &&
48
- (el.type != :p || !el.options[:transparent])
48
+ (el.type != :p || !el.options[:transparent]) &&
49
+ !([:ul, :dl, :ol].include?(el.type) && @stack.last.type == :li)
49
50
  res << "\n"
50
51
  end
51
52
  res
@@ -71,27 +72,30 @@ module Kramdown
71
72
  ""
72
73
  end
73
74
 
74
- ESCAPED_CHAR_RE = /(\$\$|[\\*_`\[\]\{"'|])|^[ ]{0,3}(:)/
75
+ ESCAPED_CHAR_RE = /(\$\$|[\\*_`\[\]{"'|])|^ {0,3}(:)/
75
76
 
76
77
  def convert_text(el, opts)
77
- if opts[:raw_text]
78
+ if opts[:raw_text] || (@stack.last.type == :html_element && @stack.last.options[:content_model] == :raw)
78
79
  el.value
79
80
  else
80
- el.value.gsub(/\A\n/) do
81
+ result = el.value.gsub(/\A\n/) do
81
82
  opts[:prev] && opts[:prev].type == :br ? '' : "\n"
82
- end.gsub(/\s+/, ' ').gsub(ESCAPED_CHAR_RE) do
83
+ end
84
+ result.gsub!(/\s+/, ' ') unless el.options[:cdata]
85
+ result.gsub!(ESCAPED_CHAR_RE) do
83
86
  $1 || !opts[:prev] || opts[:prev].type == :br ? "\\#{$1 || $2}" : $&
84
87
  end
88
+ result
85
89
  end
86
90
  end
87
91
 
88
92
  def convert_p(el, opts)
89
93
  w = @options[:line_width] - opts[:indent].to_s.to_i
90
94
  first, second, *rest = inner(el, opts).strip.gsub(/(.{1,#{w}})( +|$\n?)/, "\\1\n").split(/\n/)
91
- first&.gsub!(/^(?:(#|>)|(\d+)\.|([+-]\s))/) { $1 || $3 ? "\\#{$1 || $3}" : "#{$2}\\." }
95
+ first&.gsub!(/^(?:(#|>)|(\d+)\.(\s)|([+-]\s))/) { $1 || $4 ? "\\#{$1 || $4}" : "#{$2}\\.#{$3}" }
92
96
  second&.gsub!(/^([=-]+\s*?)$/, "\\\1")
93
97
  res = [first, second, *rest].compact.join("\n") + "\n"
94
- res.gsub!(/^[ ]{0,3}:/, "\\:")
98
+ res.gsub!(/^ {0,3}:/, "\\:")
95
99
  if el.children.length == 1 && el.children.first.type == :math
96
100
  res = "\\#{res}"
97
101
  elsif res.start_with?('\$$') && res.end_with?("\\$$\n")
@@ -101,15 +105,16 @@ module Kramdown
101
105
  end
102
106
 
103
107
  def convert_codeblock(el, _opts)
104
- el.value.split(/\n/).map {|l| l.empty? ? " " : " #{l}" }.join("\n") + "\n"
108
+ el.value.split("\n").map {|l| l.empty? ? " " : " #{l}" }.join("\n") + "\n"
105
109
  end
106
110
 
107
111
  def convert_blockquote(el, opts)
108
112
  opts[:indent] += 2
109
- inner(el, opts).chomp.split(/\n/).map {|l| "> #{l}" }.join("\n") << "\n"
113
+ inner(el, opts).chomp.split("\n").map {|l| "> #{l}" }.join("\n") << "\n"
110
114
  end
111
115
 
112
116
  def convert_header(el, opts)
117
+ opts[:in_header] = true
113
118
  res = +''
114
119
  res << "#{'#' * output_header_level(el.options[:level])} #{inner(el, opts)}"
115
120
  res[-1, 1] = "\\#" if res[-1] == '#'
@@ -140,13 +145,13 @@ module Kramdown
140
145
  opts[:indent] += width
141
146
  text = inner(el, opts)
142
147
  newlines = text.scan(/\n*\Z/).first
143
- first, *last = text.split(/\n/)
148
+ first, *last = text.split("\n")
144
149
  last = last.map {|l| " " * width + l }.join("\n")
145
150
  text = (first.nil? ? "\n" : first + (last.empty? ? "" : "\n") + last + newlines)
146
151
  if el.children.first && el.children.first.type == :p && !el.children.first.options[:transparent]
147
152
  res = +"#{sym}#{text}"
148
153
  res << "^\n" if el.children.size == 1 && @stack.last.children.last == el &&
149
- (@stack.last.children.any? {|c| c.children.first.type != :p } || @stack.last.children.size == 1)
154
+ (@stack.last.children.any? {|c| !c.children.first || c.children.first.type != :p } || @stack.last.children.size == 1)
150
155
  res
151
156
  elsif el.children.first && el.children.first.type == :codeblock
152
157
  "#{sym}\n #{text}"
@@ -164,7 +169,7 @@ module Kramdown
164
169
  opts[:indent] += width
165
170
  text = inner(el, opts)
166
171
  newlines = text.scan(/\n*\Z/).first
167
- first, *last = text.split(/\n/)
172
+ first, *last = text.split("\n")
168
173
  last = last.map {|l| " " * width + l }.join("\n")
169
174
  text = first.to_s + (last.empty? ? "" : "\n") + last + newlines
170
175
  text.chomp! if text =~ /\n\n\Z/ && opts[:next] && opts[:next].type == :dd
@@ -187,7 +192,7 @@ module Kramdown
187
192
  result << inner(el, opts) << "\n"
188
193
  end
189
194
 
190
- HTML_TAGS_WITH_BODY = ['div', 'script', 'iframe', 'textarea', 'th', 'td']
195
+ HTML_TAGS_WITH_BODY = %w[div script iframe textarea th td]
191
196
 
192
197
  HTML_ELEMENT_TYPES = [:entity, :text, :html_element].freeze
193
198
  private_constant :HTML_ELEMENT_TYPES
@@ -243,7 +248,7 @@ module Kramdown
243
248
 
244
249
  def convert_thead(el, opts)
245
250
  rows = inner(el, opts)
246
- if opts[:alignment].all? {|a| a == :default }
251
+ if opts[:alignment].all?(:default)
247
252
  "#{rows}|#{'-' * 10}\n"
248
253
  else
249
254
  "#{rows}| " + opts[:alignment].map do |a|
@@ -284,8 +289,8 @@ module Kramdown
284
289
  end
285
290
  end
286
291
 
287
- def convert_br(_el, _opts)
288
- " \n"
292
+ def convert_br(_el, opts)
293
+ opts[:in_header] ? "<br />" : " \n"
289
294
  end
290
295
 
291
296
  def convert_a(el, opts)
@@ -367,7 +372,7 @@ module Kramdown
367
372
  end
368
373
 
369
374
  def convert_smart_quote(el, _opts)
370
- el.value.to_s =~ /[rl]dquo/ ? "\"" : "'"
375
+ el.value.to_s.match?(/[rl]dquo/) ? "\"" : "'"
371
376
  end
372
377
 
373
378
  def convert_math(el, _opts)
@@ -400,7 +405,7 @@ module Kramdown
400
405
  res = +''
401
406
  @footnotes.each do |name, data|
402
407
  res << "[^#{name}]:\n"
403
- res << inner(data).chomp.split(/\n/).map {|l| " #{l}" }.join("\n") + "\n\n"
408
+ res << inner(data).chomp.split("\n").map {|l| " #{l}" }.join("\n") + "\n\n"
404
409
  end
405
410
  res
406
411
  end
@@ -422,14 +427,14 @@ module Kramdown
422
427
  next if el.type == :header && k == 'id' && !v.strip.empty?
423
428
  if v.nil?
424
429
  ''
425
- elsif k == 'class' && !v.empty? && !v.index(/[\.#]/)
430
+ elsif k == 'class' && !v.empty? && !v.index(/[.#]/)
426
431
  " " + v.split(/\s+/).map {|w| ".#{w}" }.join(" ")
427
432
  elsif k == 'id' && !v.strip.empty?
428
433
  " ##{v}"
429
434
  else
430
435
  " #{k}=\"#{v}\""
431
436
  end
432
- end.compact.join('')
437
+ end.compact.join
433
438
  res = "toc" + (res.strip.empty? ? '' : " #{res}") if (el.type == :ul || el.type == :ol) &&
434
439
  el.options.dig(:ial, :refs)&.include?('toc')
435
440
  res = "footnotes" + (res.strip.empty? ? '' : " #{res}") if (el.type == :ul || el.type == :ol) &&
@@ -59,7 +59,7 @@ module Kramdown
59
59
  end
60
60
 
61
61
  def convert_blank(_el, opts)
62
- opts[:result] =~ /\n\n\Z|\A\Z/ ? "" : "\n"
62
+ opts[:result].match?(/\n\n\Z|\A\Z/) ? "" : "\n"
63
63
  end
64
64
 
65
65
  def convert_text(el, _opts)
@@ -153,9 +153,10 @@ module Kramdown
153
153
  end
154
154
 
155
155
  def convert_html_element(el, opts)
156
- if el.value == 'i' || el.value == 'em'
156
+ case el.value
157
+ when 'i', 'em'
157
158
  "\\emph{#{inner(el, opts)}}"
158
- elsif el.value == 'b' || el.value == 'strong'
159
+ when 'b', 'strong'
159
160
  "\\textbf{#{inner(el, opts)}}"
160
161
  else
161
162
  warning("Can't convert HTML element")
@@ -164,7 +165,7 @@ module Kramdown
164
165
  end
165
166
 
166
167
  def convert_xml_comment(el, _opts)
167
- el.value.split(/\n/).map {|l| "% #{l}" }.join("\n") + "\n"
168
+ el.value.split("\n").map {|l| "% #{l}" }.join("\n") + "\n"
168
169
  end
169
170
 
170
171
  def convert_xml_pi(_el, _opts)
@@ -203,7 +204,7 @@ module Kramdown
203
204
  end
204
205
 
205
206
  def convert_comment(el, _opts)
206
- el.value.split(/\n/).map {|l| "% #{l}" }.join("\n") << "\n"
207
+ el.value.split("\n").map {|l| "% #{l}" }.join("\n") << "\n"
207
208
  end
208
209
 
209
210
  def convert_br(_el, opts)
@@ -224,7 +225,7 @@ module Kramdown
224
225
 
225
226
  def convert_img(el, _opts)
226
227
  line = el.options[:location]
227
- if el.attr['src'] =~ /^(https?|ftps?):\/\//
228
+ if el.attr['src'].match?(/^(https?|ftps?):\/\//)
228
229
  warning("Cannot include non-local image#{line ? " (line #{line})" : ''}")
229
230
  ''
230
231
  elsif !el.attr['src'].empty?
@@ -556,7 +557,7 @@ module Kramdown
556
557
  def convert_math(el, _opts)
557
558
  @data[:packages] += %w[amssymb amsmath amsthm amsfonts]
558
559
  if el.options[:category] == :block
559
- if el.value =~ /\A\s*\\begin\{/
560
+ if el.value.match?(/\A\s*\\begin\{/)
560
561
  el.value
561
562
  else
562
563
  latex_environment('displaymath', el, el.value)
@@ -573,7 +574,7 @@ module Kramdown
573
574
 
574
575
  # Normalize the abbreviation key so that it only contains allowed ASCII character
575
576
  def normalize_abbreviation_key(key)
576
- key.gsub(/\W/) {|m| m.unpack('H*').first }
577
+ key.gsub(/\W/) {|m| m.unpack1('H*') }
577
578
  end
578
579
 
579
580
  # Wrap the +text+ inside a LaTeX environment of type +type+. The element +el+ is passed on to
@@ -597,7 +598,7 @@ module Kramdown
597
598
 
598
599
  # Return a LaTeX comment containing all attributes as 'key="value"' pairs.
599
600
  def attribute_list(el)
600
- attrs = el.attr.map {|k, v| v.nil? ? '' : " #{k}=\"#{v}\"" }.compact.sort.join('')
601
+ attrs = el.attr.map {|k, v| v.nil? ? '' : " #{k}=\"#{v}\"" }.compact.sort.join
601
602
  attrs = " % #{attrs}" unless attrs.empty?
602
603
  attrs
603
604
  end
@@ -611,7 +612,7 @@ module Kramdown
611
612
  ">" => "\\textgreater{}",
612
613
  "[" => "{[}",
613
614
  "]" => "{]}",
614
- }.merge(Hash[*("{}$%&_#".each_char.map {|c| [c, "\\#{c}"] }.flatten)]) # :nodoc:
615
+ }.merge(Hash[*"{}$%&_#".each_char.map {|c| [c, "\\#{c}"] }.flatten]) # :nodoc:
615
616
  ESCAPE_RE = Regexp.union(*ESCAPE_MAP.collect {|k, _v| k }) # :nodoc:
616
617
 
617
618
  # Escape the special LaTeX characters in the string +str+.
@@ -17,7 +17,7 @@ module Kramdown
17
17
  # man-pages(7) for information regarding the output.
18
18
  class Man < Base
19
19
 
20
- def convert(el, opts = {indent: 0, result: +''}) #:nodoc:
20
+ def convert(el, opts = {indent: 0, result: +''}) # :nodoc:
21
21
  send("convert_#{el.type}", el, opts)
22
22
  end
23
23
 
@@ -139,7 +139,7 @@ module Kramdown
139
139
  def convert_table(el, opts)
140
140
  opts[:alignment] = el.options[:alignment].map {|a| TABLE_CELL_ALIGNMENT[a] }
141
141
  table_options = ["box"]
142
- table_options << "center" if el.attr['class'] =~ /\bcenter\b/
142
+ table_options << "center" if el.attr['class']&.match?(/\bcenter\b/)
143
143
  opts[:result] << macro("TS") << "#{table_options.join(' ')} ;\n"
144
144
  inner(el, opts)
145
145
  opts[:result] << macro("TE") << macro("sp")
@@ -171,7 +171,7 @@ module Kramdown
171
171
  result = opts[:result]
172
172
  opts[:result] = +''
173
173
  inner(el, opts)
174
- if opts[:result] =~ /\n/
174
+ if opts[:result].include?("\n")
175
175
  warning("Table cells using links are not supported")
176
176
  result << "\t"
177
177
  else
@@ -17,7 +17,7 @@ module Kramdown::Converter::MathEngine
17
17
 
18
18
  def self.call(converter, el, opts)
19
19
  value = converter.escape_html(el.value)
20
- result = el.options[:category] == :block ? "\\[#{value}\\]\n" : "\\(#{value}\\)"
20
+ result = el.options[:category] == :block ? "\\[#{value}\\]\n" : "\\(#{value}\\)"
21
21
  if el.attr.empty?
22
22
  result
23
23
  elsif el.options[:category] == :block
@@ -35,12 +35,13 @@ module Kramdown
35
35
  children = el.children.dup
36
36
  index = 0
37
37
  while index < children.length
38
- if [:xml_pi].include?(children[index].type) ||
39
- (children[index].type == :html_element && %w[style script].include?(children[index].value))
38
+ if children[index].type == :xml_pi ||
39
+ (children[index].type == :html_element && (children[index].value == 'style' ||
40
+ children[index].value == 'script'))
40
41
  children[index..index] = []
41
42
  elsif children[index].type == :html_element &&
42
- ((@options[:remove_block_html_tags] && children[index].options[:category] == :block) ||
43
- (@options[:remove_span_html_tags] && children[index].options[:category] == :span))
43
+ ((@options[:remove_block_html_tags] && children[index].options[:category] == :block) ||
44
+ (@options[:remove_span_html_tags] && children[index].options[:category] == :span))
44
45
  children[index..index] = children[index].children
45
46
  else
46
47
  convert(children[index])
@@ -121,7 +121,7 @@ module Kramdown
121
121
  end
122
122
  end
123
123
 
124
- def inspect #:nodoc:
124
+ def inspect # :nodoc:
125
125
  "<KD:Document: options=#{@options.inspect} root=#{@root.inspect} warnings=#{@warnings.inspect}>"
126
126
  end
127
127
 
@@ -508,7 +508,7 @@ module Kramdown
508
508
  @options ||= {}
509
509
  end
510
510
 
511
- def inspect #:nodoc:
511
+ def inspect # :nodoc:
512
512
  "<kd:#{@type}" \
513
513
  "#{value.nil? ? '' : ' value=' + value.inspect}" \
514
514
  "#{attr.empty? ? '' : ' attr=' + attr.inspect}" \