kramdown 2.0.0.beta2 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of kramdown might be problematic. Click here for more details.

Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTERS +14 -3
  3. data/VERSION +1 -1
  4. data/bin/kramdown +48 -19
  5. data/lib/kramdown/converter/base.rb +2 -1
  6. data/lib/kramdown/converter/html.rb +47 -25
  7. data/lib/kramdown/converter/kramdown.rb +11 -6
  8. data/lib/kramdown/converter/latex.rb +1 -1
  9. data/lib/kramdown/converter/math_engine/mathjax.rb +7 -33
  10. data/lib/kramdown/converter/syntax_highlighter.rb +1 -1
  11. data/lib/kramdown/converter/syntax_highlighter/rouge.rb +20 -9
  12. data/lib/kramdown/element.rb +30 -3
  13. data/lib/kramdown/options.rb +57 -8
  14. data/lib/kramdown/parser/base.rb +3 -1
  15. data/lib/kramdown/parser/html.rb +8 -8
  16. data/lib/kramdown/parser/kramdown.rb +11 -2
  17. data/lib/kramdown/parser/kramdown/autolink.rb +2 -2
  18. data/lib/kramdown/parser/kramdown/blank_line.rb +2 -2
  19. data/lib/kramdown/parser/kramdown/block_boundary.rb +3 -2
  20. data/lib/kramdown/parser/kramdown/codespan.rb +12 -2
  21. data/lib/kramdown/parser/kramdown/emphasis.rb +1 -1
  22. data/lib/kramdown/parser/kramdown/extensions.rb +14 -8
  23. data/lib/kramdown/parser/kramdown/header.rb +3 -2
  24. data/lib/kramdown/parser/kramdown/html.rb +4 -10
  25. data/lib/kramdown/parser/kramdown/link.rb +3 -2
  26. data/lib/kramdown/parser/kramdown/list.rb +64 -33
  27. data/lib/kramdown/parser/kramdown/math.rb +1 -1
  28. data/lib/kramdown/parser/kramdown/paragraph.rb +3 -3
  29. data/lib/kramdown/parser/kramdown/table.rb +3 -3
  30. data/lib/kramdown/utils/html.rb +9 -0
  31. data/lib/kramdown/version.rb +1 -1
  32. data/man/man1/kramdown.1 +31 -1
  33. data/test/test_files.rb +18 -11
  34. data/test/test_location.rb +2 -2
  35. data/test/test_string_scanner_kramdown.rb +1 -1
  36. data/test/testcases/block/03_paragraph/standalone_image.html +8 -0
  37. data/test/testcases/block/03_paragraph/standalone_image.text +6 -0
  38. data/test/testcases/block/04_header/atx_header.html +6 -0
  39. data/test/testcases/block/04_header/atx_header.text +6 -0
  40. data/test/testcases/block/06_codeblock/guess_lang_css_class.html +15 -0
  41. data/test/testcases/block/06_codeblock/guess_lang_css_class.options +2 -0
  42. data/test/testcases/block/06_codeblock/guess_lang_css_class.text +13 -0
  43. data/test/testcases/block/09_html/processing_instruction.html +5 -6
  44. data/test/testcases/block/09_html/standalone_image_in_div.htmlinput +7 -0
  45. data/test/testcases/block/09_html/standalone_image_in_div.text +8 -0
  46. data/test/testcases/block/12_extension/options.html +4 -4
  47. data/test/testcases/block/12_extension/options.text +2 -0
  48. data/test/testcases/block/12_extension/options2.html +4 -4
  49. data/test/testcases/block/14_table/table_with_footnote.html +4 -4
  50. data/test/testcases/block/15_math/gh_128.html +1 -2
  51. data/test/testcases/block/15_math/normal.html +16 -15
  52. data/test/testcases/block/16_toc/toc_with_footnotes.html +4 -4
  53. data/test/testcases/cjk-line-break.html +4 -0
  54. data/test/testcases/cjk-line-break.options +1 -0
  55. data/test/testcases/cjk-line-break.text +12 -0
  56. data/test/testcases/span/02_emphasis/normal.html +4 -0
  57. data/test/testcases/span/02_emphasis/normal.text +4 -0
  58. data/test/testcases/span/03_codespan/normal-css-class.html +1 -0
  59. data/test/testcases/span/03_codespan/normal-css-class.options +2 -0
  60. data/test/testcases/span/03_codespan/normal-css-class.text +1 -0
  61. data/test/testcases/span/04_footnote/backlink_inline.html +21 -21
  62. data/test/testcases/span/04_footnote/backlink_text.html +4 -4
  63. data/test/testcases/span/04_footnote/footnote_nr.html +6 -6
  64. data/test/testcases/span/04_footnote/footnote_prefix.html +12 -0
  65. data/test/testcases/span/04_footnote/footnote_prefix.options +1 -0
  66. data/test/testcases/span/04_footnote/footnote_prefix.text +4 -0
  67. data/test/testcases/span/04_footnote/inside_footnote.html +9 -9
  68. data/test/testcases/span/04_footnote/markers.html +16 -16
  69. data/test/testcases/span/04_footnote/placement.html +4 -4
  70. data/test/testcases/span/04_footnote/regexp_problem.html +4 -4
  71. data/test/testcases/span/04_footnote/without_backlink.html +3 -3
  72. data/test/testcases/span/05_html/normal.html +1 -1
  73. data/test/testcases/span/abbreviations/in_footnote.html +4 -4
  74. data/test/testcases/span/math/normal.html +4 -4
  75. metadata +35 -15
  76. data/test/testcases/block/15_math/mathjax_preview.html +0 -4
  77. data/test/testcases/block/15_math/mathjax_preview.options +0 -2
  78. data/test/testcases/block/15_math/mathjax_preview.text +0 -5
  79. data/test/testcases/block/15_math/mathjax_preview_as_code.html +0 -4
  80. data/test/testcases/block/15_math/mathjax_preview_as_code.options +0 -3
  81. data/test/testcases/block/15_math/mathjax_preview_as_code.text +0 -5
  82. data/test/testcases/block/15_math/mathjax_preview_simple.html +0 -4
  83. data/test/testcases/block/15_math/mathjax_preview_simple.options +0 -2
  84. data/test/testcases/block/15_math/mathjax_preview_simple.text +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f737523fd370cb69aff3ae9bb1c7fbad526081be7d3df2275de8fb9563d9c4c2
4
- data.tar.gz: 81ca8a7bb1aa6feecbad1cbe0cba3eeebb26751ff9b1e33692f0f0f663f76a3d
3
+ metadata.gz: 2a893196013756c877e4baa3d62eb2d3b862684748ed4f329a9723779e30bbeb
4
+ data.tar.gz: abfac14092805a87a5bdb0c7210ddb157b35a22391a8393a8401fdc547d2f902
5
5
  SHA512:
6
- metadata.gz: 5e5cd66bdc510a27fa640fe0ed18d598c3f4acda9dcd8fe54b931f00ea08011e16772881f6e3b3a17338412cd03ea6af57e8687102601cdde24c6da195fa67f4
7
- data.tar.gz: 06202fba99c3a55af853235d3c1d355856b085d30cc5d4d29bfbde3587a01c258663a4b47b12ce60e649ceeb2b1e72cca66c1d434ae662bfdd07221ba75d8d73
6
+ metadata.gz: 2fdb47e22271964a0a5caef5dc9054a6a5d50cfd81c01665ddfe9aa8e66539ce97125019bea46700ff54227602ce45fd3af98bd48824fe3460aefd6ce6ec3828
7
+ data.tar.gz: 9927a0d0fe778ac799dcd499727623c7bb35cc2a46a5745042c88d65685502d7bc04384c265155af214f046a2a27f72cf4b73b2d3ddba6a987de85939b6cfe56
@@ -1,17 +1,19 @@
1
1
  Count Name
2
2
  ======= ====
3
- 895 Thomas Leitner <t_leitner@gmx.at>
3
+ 943 Thomas Leitner <t_leitner@gmx.at>
4
+ 18 Ashwin Maroli <ashmaroli@gmail.com>
4
5
  7 Christian Cornelssen <ccorn@1tein.de>
5
6
  6 Gioele Barabucci <gioele@svario.it>
7
+ 5 Gleb Mazovetskiy <glex.spb@gmail.com>
6
8
  4 Ted Pak <powerpak006@gmail.com>
7
9
  4 Shuanglei Tao <tsl0922@gmail.com>
8
- 4 Gleb Mazovetskiy <glex.spb@gmail.com>
9
10
  4 Dan Allen <dan.j.allen@gmail.com>
10
11
  4 Arne Brasseur <arne@arnebrasseur.net>
11
12
  3 Henning Perl <perl@fast-sicher.de>
12
13
  3 gettalong <t_leitner@gmx.at>
13
14
  3 Brandur <brandur@mutelight.org>
14
15
  3 Ben Armston <ben.armston@googlemail.com>
16
+ 3 Ashwin Maroli <ashmaroli@users.noreply.github.com>
15
17
  3 Alex Marandon <contact@alexmarandon.com>
16
18
  2 Tom Thorogood <me+github@tomthorogood.co.uk>
17
19
  2 Parker Moore <parkrmoore@gmail.com>
@@ -25,20 +27,25 @@
25
27
  1 utenmiki <utenmiki@gmail.com>
26
28
  1 Trevor Wennblom <trevor@well.com>
27
29
  1 tomykaira <tomykaira@gmail.com>
30
+ 1 tom93 <tomlevy93@gmail.com>
28
31
  1 Tim Blair <tim@bla.ir>
29
32
  1 Tim Besard <tim.besard@gmail.com>
30
33
  1 Tim Bates <tim@rumpuslabs.com>
31
34
  1 Sun Yaozhu <yzyzsun@gmail.com>
35
+ 1 Stephen <stephengroat@users.noreply.github.com>
32
36
  1 Stephen Crosby <stevecrozz@gmail.com>
33
37
  1 Simon Lydell <simon.lydell@gmail.com>
38
+ 1 Simon Coffey <simon.coffey@futurelearn.com>
34
39
  1 Shusaku NAKAZATO <cu393uc@gmail.com>
35
40
  1 Sebastian Boehm <sebastian@sometimesfood.org>
36
41
  1 scherr <maximilianscherr@gmail.com>
37
42
  1 Postmodern <postmodern.mod3@gmail.com>
38
43
  1 Pete Michaud <michaudp@gmail.com>
44
+ 1 Noah Doersing <doersino@gmail.com>
39
45
  1 myqlarson <myqlarson@gmail.com>
40
46
  1 milo.simpson <milo.simpson@bazaarvoice.com>
41
47
  1 Michal Till <michal.till@gmail.com>
48
+ 1 Maxime Kjaer <maxime.kjaer@gmail.com>
42
49
  1 Matt Hickford <matt.hickford@gmail.com>
43
50
  1 Martyn Chamberlin <martyn@perfectioncoding.com>
44
51
  1 Marek Tuchowski <marek@tuchowski.com.pl>
@@ -55,13 +62,17 @@
55
62
  1 Hector Correa <hector@hectorcorrea.com>
56
63
  1 Florian Klampfer <f.klampfer@gmail.com>
57
64
  1 Floreal Morandat florealm@gmail.com <florealm@gmail.com>
65
+ 1 Fangyi Zhou <me@fangyi.io>
58
66
  1 Diego Galeota <diegobg123@gmail.com>
67
+ 1 David Rodríguez <deivid.rodriguez@riseup.net>
59
68
  1 Damien Pollet <damien.pollet@gmail.com>
60
69
  1 Christopher Jefferson <caj21@st-andrews.ac.uk>
61
70
  1 Cédric Boutillier <cedric.boutillier@gmail.com>
62
- 1 Ashwin Maroli <ashmaroli@gmail.com>
71
+ 1 Bob Lail <lail@squareup.com>
63
72
  1 Ashe Connor <ashe@kivikakk.ee>
73
+ 1 Antoine Cotten <hello@acotten.com>
64
74
  1 Andrew <andrew.dale.wylie@gmail.com>
65
75
  1 Alpha Chen <alpha.chen@gmail.com>
66
76
  1 Alex Tomlins <alex.tomlins@digital.cabinet-office.gov.uk>
67
77
  1 Alexey Vasiliev <le0pard@users.noreply.github.com>
78
+ 1 284km <k.furuhashi10@gmail.com>
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.0.beta1
1
+ 2.3.0
@@ -13,6 +13,37 @@ require 'rbconfig'
13
13
  require 'yaml'
14
14
  require 'kramdown'
15
15
 
16
+ def add_kramdown_options(opts, parsed_options, banner: [], ignore: [])
17
+ banner_shown = false
18
+ defined_options = []
19
+ Kramdown::Options.definitions.sort.each do |n, definition|
20
+ next if ignore.include?(n)
21
+
22
+ unless banner_shown
23
+ opts.separator("")
24
+ banner.each {|part| opts.separator(part) }
25
+ opts.separator("")
26
+ banner_shown = true
27
+ end
28
+
29
+ defined_options << n
30
+ no = n.to_s.tr('_', '-')
31
+ if definition.type == Kramdown::Options::Boolean
32
+ opts.on("--[no-]#{no}") {|v| parsed_options[n] = Kramdown::Options.parse(n, v) }
33
+ else
34
+ type = definition.type
35
+ type = String if type == Symbol || type == Object
36
+ opts.on("--#{no} ARG", type) {|v| parsed_options[n] = Kramdown::Options.parse(n, v) }
37
+ end
38
+
39
+ definition.desc.split(/\n/).each do |line|
40
+ opts.separator opts.summary_indent + ' ' * 6 + line
41
+ end
42
+ opts.separator ''
43
+ end
44
+ defined_options
45
+ end
46
+
16
47
  config_file = nil
17
48
  begin
18
49
  config_dir = case RbConfig::CONFIG['host_os']
@@ -30,6 +61,7 @@ end
30
61
  options = {}
31
62
  format = ['html']
32
63
 
64
+ defined_options = []
33
65
  OptionParser.new do |opts|
34
66
  opts.banner = "Usage: kramdown [options] [FILE FILE ...]"
35
67
  opts.summary_indent = ' ' * 4
@@ -42,6 +74,20 @@ OptionParser.new do |opts|
42
74
  "html, or markdown") {|v| options[:input] = v }
43
75
  opts.on("-o", "--output ARG", Array, "Specify one or more output formats separated by commas: " \
44
76
  "html (default),", "kramdown, latex, man or remove_html_tags") {|v| format = v }
77
+ opts.on("-x", "--extension EXT", Array, "Load one or more extensions (without the 'kramdown-' " \
78
+ "prefix) separated", "by commas (e.g. parser-gfm,syntax-coderay)",
79
+ "Note: Use this option before other options!") do |exts|
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
89
+ end
90
+ end
45
91
  opts.separator ""
46
92
  opts.on("--no-config-file", "Do not read any configuration file. Default behavior is to check " \
47
93
  "for a", "configuration file and read it if it exists.") { config_file = nil }
@@ -59,25 +105,8 @@ OptionParser.new do |opts|
59
105
  exit
60
106
  end
61
107
 
62
- opts.separator ""
63
- opts.separator "kramdown options:"
64
- opts.separator ""
65
-
66
- Kramdown::Options.definitions.sort.each do |n, definition|
67
- no = n.to_s.tr('_', '-')
68
- if definition.type == Kramdown::Options::Boolean
69
- opts.on("--[no-]#{no}") {|v| options[n] = Kramdown::Options.parse(n, v) }
70
- else
71
- type = definition.type
72
- type = String if type == Symbol || type == Object
73
- opts.on("--#{no} ARG", type) {|v| options[n] = Kramdown::Options.parse(n, v) }
74
- end
75
-
76
- definition.desc.split(/\n/).each do |line|
77
- opts.separator opts.summary_indent + ' ' * 6 + line
78
- end
79
- opts.separator ''
80
- end
108
+ new_options = add_kramdown_options(opts, options, banner: ["kramdown options:"])
109
+ defined_options.concat(new_options)
81
110
  end.parse!
82
111
 
83
112
  begin
@@ -106,7 +106,8 @@ module Kramdown
106
106
  end
107
107
  result = converter.convert(tree)
108
108
  if result.respond_to?(:encode!) && result.encoding != Encoding::BINARY
109
- result.encode!(tree.options[:encoding])
109
+ result.encode!(tree.options[:encoding] ||
110
+ (raise ::Kramdown::Error, "Missing encoding option on root element"))
110
111
  end
111
112
  if !converter.options[:template].empty? && converter.apply_template_after?
112
113
  result = apply_template(converter, result)
@@ -46,15 +46,16 @@ module Kramdown
46
46
  @toc_code = nil
47
47
  @indent = 2
48
48
  @stack = []
49
- end
50
49
 
51
- # The mapping of element type to conversion method.
52
- DISPATCHER = Hash.new {|h, k| h[k] = "convert_#{k}" }
50
+ # stash string representation of symbol to avoid allocations from multiple interpolations.
51
+ @highlighter_class = " highlighter-#{options[:syntax_highlighter]}"
52
+ @dispatcher = Hash.new {|h, k| h[k] = :"convert_#{k}" }
53
+ end
53
54
 
54
55
  # Dispatch the conversion of the element +el+ to a +convert_TYPE+ method using the +type+ of
55
56
  # the element.
56
57
  def convert(el, indent = -@indent)
57
- send(DISPATCHER[el.type], el, indent)
58
+ send(@dispatcher[el.type], el, indent)
58
59
  end
59
60
 
60
61
  # Return the converted content of the children of +el+ as a string. The parameter +indent+ has
@@ -67,7 +68,7 @@ module Kramdown
67
68
  indent += @indent
68
69
  @stack.push(el)
69
70
  el.children.each do |inner_el|
70
- result << send(DISPATCHER[inner_el.type], inner_el, indent)
71
+ result << send(@dispatcher[inner_el.type], inner_el, indent)
71
72
  end
72
73
  @stack.pop
73
74
  result
@@ -78,17 +79,33 @@ module Kramdown
78
79
  end
79
80
 
80
81
  def convert_text(el, _indent)
81
- escape_html(el.value, :text)
82
+ escaped = escape_html(el.value, :text)
83
+ @options[:remove_line_breaks_for_cjk] ? fix_cjk_line_break(escaped) : escaped
82
84
  end
83
85
 
84
86
  def convert_p(el, indent)
85
87
  if el.options[:transparent]
86
88
  inner(el, indent)
89
+ elsif el.children.size == 1 && el.children.first.type == :img &&
90
+ el.children.first.options[:ial]&.[](:refs)&.include?('standalone')
91
+ convert_standalone_image(el.children.first, indent)
87
92
  else
88
- format_as_block_html(el.type, el.attr, inner(el, indent), indent)
93
+ format_as_block_html("p", el.attr, inner(el, indent), indent)
89
94
  end
90
95
  end
91
96
 
97
+ # Helper method used by +convert_p+ to convert a paragraph that only contains a single :img
98
+ # element.
99
+ def convert_standalone_image(el, indent)
100
+ attr = el.attr.dup
101
+ figure_attr = {}
102
+ figure_attr['class'] = attr.delete('class') if attr.key?('class')
103
+ figure_attr['id'] = attr.delete('id') if attr.key?('id')
104
+ body = "#{' ' * (indent + @indent)}<img#{html_attributes(attr)} />\n" \
105
+ "#{' ' * (indent + @indent)}<figcaption>#{attr['alt']}</figcaption>\n"
106
+ format_as_indented_block_html("figure", figure_attr, body, indent)
107
+ end
108
+
92
109
  def convert_codeblock(el, indent)
93
110
  attr = el.attr.dup
94
111
  lang = extract_code_language!(attr)
@@ -120,7 +137,7 @@ module Kramdown
120
137
  end
121
138
 
122
139
  def convert_blockquote(el, indent)
123
- format_as_indented_block_html(el.type, el.attr, inner(el, indent), indent)
140
+ format_as_indented_block_html("blockquote", el.attr, inner(el, indent), indent)
124
141
  end
125
142
 
126
143
  def convert_header(el, indent)
@@ -137,12 +154,15 @@ module Kramdown
137
154
  "#{' ' * indent}<hr#{html_attributes(el.attr)} />\n"
138
155
  end
139
156
 
157
+ ZERO_TO_ONETWENTYEIGHT = (0..128).to_a.freeze
158
+ private_constant :ZERO_TO_ONETWENTYEIGHT
159
+
140
160
  def convert_ul(el, indent)
141
- if !@toc_code && (el.options[:ial][:refs].include?('toc') rescue nil)
142
- @toc_code = [el.type, el.attr, (0..128).to_a.map { rand(36).to_s(36) }.join]
161
+ if !@toc_code && el.options.dig(:ial, :refs)&.include?('toc')
162
+ @toc_code = [el.type, el.attr, ZERO_TO_ONETWENTYEIGHT.map { rand(36).to_s(36) }.join]
143
163
  @toc_code.last
144
- elsif !@footnote_location && el.options[:ial] && (el.options[:ial][:refs] || []).include?('footnotes')
145
- @footnote_location = (0..128).to_a.map { rand(36).to_s(36) }.join
164
+ elsif !@footnote_location && el.options.dig(:ial, :refs)&.include?('footnotes')
165
+ @footnote_location = ZERO_TO_ONETWENTYEIGHT.map { rand(36).to_s(36) }.join
146
166
  else
147
167
  format_as_indented_block_html(el.type, el.attr, inner(el, indent), indent)
148
168
  end
@@ -150,7 +170,7 @@ module Kramdown
150
170
  alias convert_ol convert_ul
151
171
 
152
172
  def convert_dl(el, indent)
153
- format_as_indented_block_html(el.type, el.attr, inner(el, indent), indent)
173
+ format_as_indented_block_html("dl", el.attr, inner(el, indent), indent)
154
174
  end
155
175
 
156
176
  def convert_li(el, indent)
@@ -173,7 +193,7 @@ module Kramdown
173
193
  break
174
194
  end
175
195
  end if !attr['id'] && @stack.last.options[:ial] && @stack.last.options[:ial][:refs]
176
- format_as_block_html(el.type, attr, inner(el, indent), indent)
196
+ format_as_block_html("dt", attr, inner(el, indent), indent)
177
197
  end
178
198
 
179
199
  def convert_html_element(el, indent)
@@ -248,7 +268,7 @@ module Kramdown
248
268
  end
249
269
 
250
270
  def convert_a(el, indent)
251
- format_as_span_html(el.type, el.attr, inner(el, indent))
271
+ format_as_span_html("a", el.attr, inner(el, indent))
252
272
  end
253
273
 
254
274
  def convert_img(el, _indent)
@@ -271,17 +291,19 @@ module Kramdown
271
291
 
272
292
  def convert_footnote(el, _indent)
273
293
  repeat = ''
274
- if (footnote = @footnotes_by_name[el.options[:name]])
294
+ name = @options[:footnote_prefix] + el.options[:name]
295
+ if (footnote = @footnotes_by_name[name])
275
296
  number = footnote[2]
276
297
  repeat = ":#{footnote[3] += 1}"
277
298
  else
278
299
  number = @footnote_counter
279
300
  @footnote_counter += 1
280
- @footnotes << [el.options[:name], el.value, number, 0]
281
- @footnotes_by_name[el.options[:name]] = @footnotes.last
301
+ @footnotes << [name, el.value, number, 0]
302
+ @footnotes_by_name[name] = @footnotes.last
282
303
  end
283
- "<sup id=\"fnref:#{el.options[:name]}#{repeat}\">" \
284
- "<a href=\"#fn:#{el.options[:name]}\" class=\"footnote\">#{number}</a></sup>"
304
+ "<sup id=\"fnref:#{name}#{repeat}\" role=\"doc-noteref\">" \
305
+ "<a href=\"#fn:#{name}\" class=\"footnote\">" \
306
+ "#{number}</a></sup>"
285
307
  end
286
308
 
287
309
  def convert_raw(el, _indent)
@@ -383,7 +405,7 @@ module Kramdown
383
405
  # Add the syntax highlighter name to the 'class' attribute of the given attribute hash. And
384
406
  # overwrites or add a "language-LANG" part using the +lang+ parameter if +lang+ is not nil.
385
407
  def add_syntax_highlighter_to_class_attr(attr, lang = nil)
386
- (attr['class'] = (attr['class'] || '') + " highlighter-#{@options[:syntax_highlighter]}").lstrip!
408
+ (attr['class'] = (attr['class'] || '') + @highlighter_class).lstrip!
387
409
  attr['class'].sub!(/\blanguage-\S+|(^)/) { "language-#{lang}#{$1 ? ' ' : ''}" } if lang
388
410
  end
389
411
 
@@ -458,9 +480,9 @@ module Kramdown
458
480
  result
459
481
  end
460
482
 
461
- FOOTNOTE_BACKLINK_FMT = "%s<a href=\"#fnref:%s\" class=\"reversefootnote\">%s</a>"
483
+ FOOTNOTE_BACKLINK_FMT = "%s<a href=\"#fnref:%s\" class=\"reversefootnote\" role=\"doc-backlink\">%s</a>"
462
484
 
463
- # Return a HTML ordered list with the footnote content for the used footnotes.
485
+ # Return an HTML ordered list with the footnote content for the used footnotes.
464
486
  def footnote_content
465
487
  ol = Element.new(:ol)
466
488
  ol.attr['start'] = @footnote_start if @footnote_start != 1
@@ -468,7 +490,7 @@ module Kramdown
468
490
  backlink_text = escape_html(@options[:footnote_backlink], :text)
469
491
  while i < @footnotes.length
470
492
  name, data, _, repeat = *@footnotes[i]
471
- li = Element.new(:li, nil, 'id' => "fn:#{name}")
493
+ li = Element.new(:li, nil, 'id' => "fn:#{name}", 'role' => 'doc-endnote')
472
494
  li.children = Marshal.load(Marshal.dump(data.children))
473
495
 
474
496
  para = nil
@@ -503,7 +525,7 @@ module Kramdown
503
525
  if ol.children.empty?
504
526
  ''
505
527
  else
506
- format_as_indented_block_html('div', {class: "footnotes"}, convert(ol, 2), 0)
528
+ format_as_indented_block_html('div', {class: "footnotes", role: "doc-endnotes"}, convert(ol, 2), 0)
507
529
  end
508
530
  end
509
531
 
@@ -34,13 +34,13 @@ module Kramdown
34
34
  res = res.dup if res.frozen?
35
35
  if ![:html_element, :li, :dt, :dd, :td].include?(el.type) && (ial = ial_for_element(el))
36
36
  res << ial
37
- res << "\n\n" if Element.category(el) == :block
37
+ res << "\n\n" if el.block?
38
38
  elsif [:ul, :dl, :ol, :codeblock].include?(el.type) && opts[:next] &&
39
39
  ([el.type, :codeblock].include?(opts[:next].type) ||
40
40
  (opts[:next].type == :blank && opts[:nnext] &&
41
41
  [el.type, :codeblock].include?(opts[:nnext].type)))
42
42
  res << "^\n\n"
43
- elsif Element.category(el) == :block &&
43
+ elsif el.block? &&
44
44
  ![:li, :dd, :dt, :td, :th, :tr, :thead, :tbody, :tfoot, :blank].include?(el.type) &&
45
45
  (el.type != :html_element || @stack.last.type != :html_element) &&
46
46
  (el.type != :p || !el.options[:transparent])
@@ -184,10 +184,15 @@ module Kramdown
184
184
 
185
185
  HTML_TAGS_WITH_BODY = ['div', 'script', 'iframe', 'textarea']
186
186
 
187
+ HTML_ELEMENT_TYPES = [:entity, :text, :html_element].freeze
188
+ private_constant :HTML_ELEMENT_TYPES
189
+
187
190
  def convert_html_element(el, opts)
188
191
  markdown_attr = el.options[:category] == :block && el.children.any? do |c|
189
- c.type != :html_element && (c.type != :p || !c.options[:transparent]) &&
190
- Element.category(c) == :block
192
+ c.type != :html_element &&
193
+ (c.type != :p || !c.options[:transparent] ||
194
+ c.children.any? {|t| !HTML_ELEMENT_TYPES.member?(t.type) }) &&
195
+ c.block?
191
196
  end
192
197
  opts[:force_raw_text] = true if %w[script pre code].include?(el.value)
193
198
  opts[:raw_text] = opts[:force_raw_text] || opts[:block_raw_text] || \
@@ -421,9 +426,9 @@ module Kramdown
421
426
  end
422
427
  end.compact.join('')
423
428
  res = "toc" + (res.strip.empty? ? '' : " #{res}") if (el.type == :ul || el.type == :ol) &&
424
- (el.options[:ial][:refs].include?('toc') rescue nil)
429
+ el.options.dig(:ial, :refs)&.include?('toc')
425
430
  res = "footnotes" + (res.strip.empty? ? '' : " #{res}") if (el.type == :ul || el.type == :ol) &&
426
- (el.options[:ial][:refs].include?('footnotes') rescue nil)
431
+ el.options.dig(:ial, :refs)&.include?('footnotes')
427
432
  if el.type == :dl && el.options[:ial] && el.options[:ial][:refs]
428
433
  auto_ids = el.options[:ial][:refs].select {|ref| ref.start_with?('auto_ids') }.join(" ")
429
434
  res = auto_ids << (res.strip.empty? ? '' : " #{res}") unless auto_ids.empty?
@@ -127,7 +127,7 @@ module Kramdown
127
127
  end
128
128
 
129
129
  def convert_ul(el, opts)
130
- if !@data[:has_toc] && (el.options[:ial][:refs].include?('toc') rescue nil)
130
+ if !@data[:has_toc] && el.options.dig(:ial, :refs)&.include?('toc')
131
131
  @data[:has_toc] = true
132
132
  '\tableofcontents'
133
133
  else
@@ -16,40 +16,14 @@ module Kramdown::Converter::MathEngine
16
16
  module Mathjax
17
17
 
18
18
  def self.call(converter, el, opts)
19
- type = el.options[:category]
20
- text = (el.value =~ /<|&/ ? "% <![CDATA[\n#{el.value} %]]>" : el.value).dup
21
- text.gsub!(/<\/?script>?/, '')
22
-
23
- preview = preview_string(converter, el, opts).dup
24
-
25
- attr = {type: "math/tex#{type == :block ? '; mode=display' : ''}"}
26
- preview << if type == :block
27
- converter.format_as_block_html('script', attr, text, opts[:indent])
28
- else
29
- converter.format_as_span_html('script', attr, text)
30
- end
31
- end
32
-
33
- def self.preview_string(converter, el, opts)
34
- preview = converter.options[:math_engine_opts][:preview]
35
- return '' unless preview
36
-
37
- preview = (preview == true ? converter.escape_html(el.value) : preview.to_s)
38
-
39
- preview_as_code = converter.options[:math_engine_opts][:preview_as_code]
40
-
41
- if el.options[:category] == :block
42
- if preview_as_code
43
- converter.format_as_block_html('pre', {'class' => 'MathJax_Preview'},
44
- converter.format_as_span_html('code', {}, preview),
45
- opts[:indent])
46
- else
47
- converter.format_as_block_html('div', {'class' => 'MathJax_Preview'}, preview,
48
- opts[:indent])
49
- end
19
+ value = converter.escape_html(el.value)
20
+ result = el.options[:category] == :block ? "\\[#{value}\\]\n" : "\\(#{value}\\)"
21
+ if el.attr.empty?
22
+ result
23
+ elsif el.options[:category] == :block
24
+ converter.format_as_block_html('div', el.attr, result, opts[:indent])
50
25
  else
51
- converter.format_as_span_html(preview_as_code ? 'code' : 'span',
52
- {'class' => 'MathJax_Preview'}, preview)
26
+ converter.format_as_span_html('span', el.attr, "$#{el.value}$")
53
27
  end
54
28
  end
55
29