kramdown 2.0.0 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTERS +13 -3
  3. data/README.md +8 -2
  4. data/VERSION +1 -1
  5. data/bin/kramdown +48 -19
  6. data/lib/kramdown/converter/base.rb +2 -1
  7. data/lib/kramdown/converter/html.rb +36 -29
  8. data/lib/kramdown/converter/kramdown.rb +12 -7
  9. data/lib/kramdown/converter/latex.rb +2 -2
  10. data/lib/kramdown/converter/math_engine/mathjax.rb +7 -33
  11. data/lib/kramdown/converter/syntax_highlighter.rb +1 -1
  12. data/lib/kramdown/converter/syntax_highlighter/rouge.rb +20 -10
  13. data/lib/kramdown/element.rb +24 -0
  14. data/lib/kramdown/options.rb +53 -12
  15. data/lib/kramdown/parser/base.rb +3 -1
  16. data/lib/kramdown/parser/html.rb +8 -8
  17. data/lib/kramdown/parser/kramdown.rb +8 -1
  18. data/lib/kramdown/parser/kramdown/abbreviation.rb +1 -1
  19. data/lib/kramdown/parser/kramdown/autolink.rb +2 -2
  20. data/lib/kramdown/parser/kramdown/blank_line.rb +2 -2
  21. data/lib/kramdown/parser/kramdown/block_boundary.rb +3 -2
  22. data/lib/kramdown/parser/kramdown/codespan.rb +13 -3
  23. data/lib/kramdown/parser/kramdown/emphasis.rb +1 -1
  24. data/lib/kramdown/parser/kramdown/extensions.rb +13 -7
  25. data/lib/kramdown/parser/kramdown/header.rb +3 -2
  26. data/lib/kramdown/parser/kramdown/html.rb +4 -10
  27. data/lib/kramdown/parser/kramdown/link.rb +3 -2
  28. data/lib/kramdown/parser/kramdown/list.rb +64 -33
  29. data/lib/kramdown/parser/kramdown/math.rb +1 -1
  30. data/lib/kramdown/parser/kramdown/paragraph.rb +3 -3
  31. data/lib/kramdown/parser/kramdown/table.rb +3 -3
  32. data/lib/kramdown/utils/html.rb +9 -0
  33. data/lib/kramdown/version.rb +1 -1
  34. data/man/man1/kramdown.1 +22 -1
  35. data/test/test_files.rb +27 -18
  36. data/test/test_location.rb +2 -2
  37. data/test/test_string_scanner_kramdown.rb +1 -1
  38. data/test/testcases/block/03_paragraph/standalone_image.html +5 -0
  39. data/test/testcases/block/03_paragraph/standalone_image.text +3 -0
  40. data/test/testcases/block/04_header/atx_header.html +6 -0
  41. data/test/testcases/block/04_header/atx_header.text +6 -0
  42. data/test/testcases/block/06_codeblock/guess_lang_css_class.html +15 -0
  43. data/test/testcases/block/06_codeblock/guess_lang_css_class.options +2 -0
  44. data/test/testcases/block/06_codeblock/guess_lang_css_class.text +13 -0
  45. data/test/testcases/block/06_codeblock/rouge/multiple.html +1 -1
  46. data/test/testcases/block/06_codeblock/rouge/simple.html +1 -1
  47. data/test/testcases/block/09_html/processing_instruction.html +5 -6
  48. data/test/testcases/block/09_html/standalone_image_in_div.htmlinput +7 -0
  49. data/test/testcases/block/09_html/standalone_image_in_div.text +8 -0
  50. data/test/testcases/block/09_html/table.kramdown +8 -0
  51. data/test/testcases/block/09_html/table.text +7 -0
  52. data/test/testcases/block/12_extension/options.html +4 -4
  53. data/test/testcases/block/12_extension/options.text +2 -0
  54. data/test/testcases/block/12_extension/options2.html +4 -4
  55. data/test/testcases/block/14_table/table_with_footnote.html +4 -4
  56. data/test/testcases/block/15_math/gh_128.html +1 -2
  57. data/test/testcases/block/15_math/normal.html +16 -15
  58. data/test/testcases/block/16_toc/toc_with_footnotes.html +4 -4
  59. data/test/testcases/cjk-line-break.html +4 -0
  60. data/test/testcases/cjk-line-break.options +1 -0
  61. data/test/testcases/cjk-line-break.text +12 -0
  62. data/test/testcases/span/02_emphasis/normal.html +4 -0
  63. data/test/testcases/span/02_emphasis/normal.text +4 -0
  64. data/test/testcases/span/03_codespan/normal-css-class.html +1 -0
  65. data/test/testcases/span/03_codespan/normal-css-class.options +2 -0
  66. data/test/testcases/span/03_codespan/normal-css-class.text +1 -0
  67. data/test/testcases/span/03_codespan/normal.html +4 -0
  68. data/test/testcases/span/03_codespan/normal.text +4 -0
  69. data/test/testcases/span/04_footnote/backlink_inline.html +21 -21
  70. data/test/testcases/span/04_footnote/backlink_text.html +4 -4
  71. data/test/testcases/span/04_footnote/footnote_nr.html +6 -6
  72. data/test/testcases/span/04_footnote/footnote_prefix.html +6 -6
  73. data/test/testcases/span/04_footnote/inside_footnote.html +9 -9
  74. data/test/testcases/span/04_footnote/markers.html +16 -16
  75. data/test/testcases/span/04_footnote/placement.html +4 -4
  76. data/test/testcases/span/04_footnote/regexp_problem.html +4 -4
  77. data/test/testcases/span/04_footnote/without_backlink.html +3 -3
  78. data/test/testcases/span/05_html/normal.html +1 -1
  79. data/test/testcases/span/abbreviations/abbrev_in_html.html +9 -0
  80. data/test/testcases/span/abbreviations/abbrev_in_html.text +10 -0
  81. data/test/testcases/span/abbreviations/in_footnote.html +4 -4
  82. data/test/testcases/span/math/normal.html +4 -4
  83. data/test/testcases/span/text_substitutions/entities.html +1 -1
  84. data/test/testcases/span/text_substitutions/entities.text +1 -1
  85. metadata +40 -15
  86. data/test/testcases/block/15_math/mathjax_preview.html +0 -4
  87. data/test/testcases/block/15_math/mathjax_preview.options +0 -2
  88. data/test/testcases/block/15_math/mathjax_preview.text +0 -5
  89. data/test/testcases/block/15_math/mathjax_preview_as_code.html +0 -4
  90. data/test/testcases/block/15_math/mathjax_preview_as_code.options +0 -3
  91. data/test/testcases/block/15_math/mathjax_preview_as_code.text +0 -5
  92. data/test/testcases/block/15_math/mathjax_preview_simple.html +0 -4
  93. data/test/testcases/block/15_math/mathjax_preview_simple.options +0 -2
  94. 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: 1e61a5f6dbf5b13bfcf0164acaf6a0c6e8fa2cd2c39fc7368bf9f54be38e0552
4
- data.tar.gz: e03352fce83854b256596c7718dd2c48251b5851f7e1ca06012d433526b6015b
3
+ metadata.gz: eae4381ea8cc119f4cc1422de0b8c78baad5fc08b930111f66addb73776b7f81
4
+ data.tar.gz: 75c9f3f7a2385990fa9b490e073bd8d0f34efbb30e1f1b2fe80d4592c3668648
5
5
  SHA512:
6
- metadata.gz: 3bf07ed2b152212b8aa8e50383b7cfc7a38a16d11441f6c5b2790c834020e3ef8ab82e6978bd86b3334740cc4b23a407f66b744ded4ee22bb6e75b210d3668cc
7
- data.tar.gz: 0206cd73d6c8d75470701c197fb89d151e6f3c2c694b20af1068f8c4d03386f065194e92c2c3cea5ec37e72c5f52132ce282d2c80888f229811cefc62f2049ed
6
+ metadata.gz: 64dfda6f14d6080a968682c5a5f0209a0455733ffbc8bfb7caf8519971cef64a553b4fcc0e18c63812dee4ed3e703dd512abd99cdf8714c9b921e9f93c618026
7
+ data.tar.gz: bcb900ad8208a1faf047c486015b8ff45fea819e5a45716f6a3a7c04a1958301e5a499bf6baa54988890425fa4fed79fe6c414c4a68493db8a82a5be887935aa
data/CONTRIBUTERS CHANGED
@@ -1,17 +1,19 @@
1
1
  Count Name
2
2
  ======= ====
3
- 909 Thomas Leitner <t_leitner@gmx.at>
3
+ 944 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,14 +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>
64
73
  1 Antoine Cotten <hello@acotten.com>
65
74
  1 Andrew <andrew.dale.wylie@gmail.com>
66
75
  1 Alpha Chen <alpha.chen@gmail.com>
67
76
  1 Alex Tomlins <alex.tomlins@digital.cabinet-office.gov.uk>
68
77
  1 Alexey Vasiliev <le0pard@users.noreply.github.com>
78
+ 1 284km <k.furuhashi10@gmail.com>
data/README.md CHANGED
@@ -7,8 +7,14 @@ requests it is now released under the MIT license and therefore can easily be us
7
7
  projects, too.
8
8
 
9
9
  However, if you use kramdown in a commercial setting, please consider **contributing back any
10
- changes** for the benefit of the community and/or
11
- [**becoming a patron**](https://www.patreon.com/gettalong) - thanks!
10
+ changes** for the benefit of the community and/or [**becoming a
11
+ sponsor**](https://github.com/sponsors/gettalong/) or [**a
12
+ patron**](https://www.patreon.com/gettalong) - thanks!
13
+
14
+ Sponsors:
15
+
16
+ * **GROSSWEBER** provides <a href="http://grossweber.com/b/kramdown" target="_blank">software
17
+ development consulting and training services</a>.
12
18
 
13
19
 
14
20
  ## Introduction
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.0
1
+ 2.3.0
data/bin/kramdown CHANGED
@@ -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,7 +79,8 @@ 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)
@@ -86,21 +88,23 @@ module Kramdown
86
88
  inner(el, indent)
87
89
  elsif el.children.size == 1 && el.children.first.type == :img &&
88
90
  el.children.first.options[:ial]&.[](:refs)&.include?('standalone')
89
- convert_standalone_image(el.children.first, indent)
91
+ convert_standalone_image(el, indent)
90
92
  else
91
- format_as_block_html(el.type, el.attr, inner(el, indent), indent)
93
+ format_as_block_html("p", el.attr, inner(el, indent), indent)
92
94
  end
93
95
  end
94
96
 
95
97
  # Helper method used by +convert_p+ to convert a paragraph that only contains a single :img
96
98
  # element.
97
99
  def convert_standalone_image(el, indent)
98
- attr = el.attr.dup
99
- figure_attr = {}
100
- figure_attr['class'] = attr.delete('class') if attr.key?('class')
101
- figure_attr['id'] = attr.delete('id') if attr.key?('id')
102
- body = "#{' ' * (indent + @indent)}<img#{html_attributes(attr)} />\n" \
103
- "#{' ' * (indent + @indent)}<figcaption>#{attr['alt']}</figcaption>\n"
100
+ figure_attr = el.attr.dup
101
+ image_attr = el.children.first.attr.dup
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')
105
+
106
+ body = "#{' ' * (indent + @indent)}<img#{html_attributes(image_attr)} />\n" \
107
+ "#{' ' * (indent + @indent)}<figcaption>#{image_attr['alt']}</figcaption>\n"
104
108
  format_as_indented_block_html("figure", figure_attr, body, indent)
105
109
  end
106
110
 
@@ -135,7 +139,7 @@ module Kramdown
135
139
  end
136
140
 
137
141
  def convert_blockquote(el, indent)
138
- format_as_indented_block_html(el.type, el.attr, inner(el, indent), indent)
142
+ format_as_indented_block_html("blockquote", el.attr, inner(el, indent), indent)
139
143
  end
140
144
 
141
145
  def convert_header(el, indent)
@@ -152,12 +156,15 @@ module Kramdown
152
156
  "#{' ' * indent}<hr#{html_attributes(el.attr)} />\n"
153
157
  end
154
158
 
159
+ ZERO_TO_ONETWENTYEIGHT = (0..128).to_a.freeze
160
+ private_constant :ZERO_TO_ONETWENTYEIGHT
161
+
155
162
  def convert_ul(el, indent)
156
- if !@toc_code && (el.options[:ial][:refs].include?('toc') rescue nil)
157
- @toc_code = [el.type, el.attr, (0..128).to_a.map { rand(36).to_s(36) }.join]
163
+ if !@toc_code && el.options.dig(:ial, :refs)&.include?('toc')
164
+ @toc_code = [el.type, el.attr, ZERO_TO_ONETWENTYEIGHT.map { rand(36).to_s(36) }.join]
158
165
  @toc_code.last
159
- elsif !@footnote_location && el.options[:ial] && (el.options[:ial][:refs] || []).include?('footnotes')
160
- @footnote_location = (0..128).to_a.map { rand(36).to_s(36) }.join
166
+ elsif !@footnote_location && el.options.dig(:ial, :refs)&.include?('footnotes')
167
+ @footnote_location = ZERO_TO_ONETWENTYEIGHT.map { rand(36).to_s(36) }.join
161
168
  else
162
169
  format_as_indented_block_html(el.type, el.attr, inner(el, indent), indent)
163
170
  end
@@ -165,7 +172,7 @@ module Kramdown
165
172
  alias convert_ol convert_ul
166
173
 
167
174
  def convert_dl(el, indent)
168
- format_as_indented_block_html(el.type, el.attr, inner(el, indent), indent)
175
+ format_as_indented_block_html("dl", el.attr, inner(el, indent), indent)
169
176
  end
170
177
 
171
178
  def convert_li(el, indent)
@@ -188,7 +195,7 @@ module Kramdown
188
195
  break
189
196
  end
190
197
  end if !attr['id'] && @stack.last.options[:ial] && @stack.last.options[:ial][:refs]
191
- format_as_block_html(el.type, attr, inner(el, indent), indent)
198
+ format_as_block_html("dt", attr, inner(el, indent), indent)
192
199
  end
193
200
 
194
201
  def convert_html_element(el, indent)
@@ -263,7 +270,7 @@ module Kramdown
263
270
  end
264
271
 
265
272
  def convert_a(el, indent)
266
- format_as_span_html(el.type, el.attr, inner(el, indent))
273
+ format_as_span_html("a", el.attr, inner(el, indent))
267
274
  end
268
275
 
269
276
  def convert_img(el, _indent)
@@ -296,8 +303,8 @@ module Kramdown
296
303
  @footnotes << [name, el.value, number, 0]
297
304
  @footnotes_by_name[name] = @footnotes.last
298
305
  end
299
- "<sup id=\"fnref:#{name}#{repeat}\">" \
300
- "<a href=\"#fn:#{name}\" class=\"footnote\">" \
306
+ "<sup id=\"fnref:#{name}#{repeat}\" role=\"doc-noteref\">" \
307
+ "<a href=\"#fn:#{name}\" class=\"footnote\" rel=\"footnote\">" \
301
308
  "#{number}</a></sup>"
302
309
  end
303
310
 
@@ -400,7 +407,7 @@ module Kramdown
400
407
  # Add the syntax highlighter name to the 'class' attribute of the given attribute hash. And
401
408
  # overwrites or add a "language-LANG" part using the +lang+ parameter if +lang+ is not nil.
402
409
  def add_syntax_highlighter_to_class_attr(attr, lang = nil)
403
- (attr['class'] = (attr['class'] || '') + " highlighter-#{@options[:syntax_highlighter]}").lstrip!
410
+ (attr['class'] = (attr['class'] || '') + @highlighter_class).lstrip!
404
411
  attr['class'].sub!(/\blanguage-\S+|(^)/) { "language-#{lang}#{$1 ? ' ' : ''}" } if lang
405
412
  end
406
413
 
@@ -475,9 +482,9 @@ module Kramdown
475
482
  result
476
483
  end
477
484
 
478
- FOOTNOTE_BACKLINK_FMT = "%s<a href=\"#fnref:%s\" class=\"reversefootnote\">%s</a>"
485
+ FOOTNOTE_BACKLINK_FMT = "%s<a href=\"#fnref:%s\" class=\"reversefootnote\" role=\"doc-backlink\">%s</a>"
479
486
 
480
- # Return a HTML ordered list with the footnote content for the used footnotes.
487
+ # Return an HTML ordered list with the footnote content for the used footnotes.
481
488
  def footnote_content
482
489
  ol = Element.new(:ol)
483
490
  ol.attr['start'] = @footnote_start if @footnote_start != 1
@@ -485,7 +492,7 @@ module Kramdown
485
492
  backlink_text = escape_html(@options[:footnote_backlink], :text)
486
493
  while i < @footnotes.length
487
494
  name, data, _, repeat = *@footnotes[i]
488
- li = Element.new(:li, nil, 'id' => "fn:#{name}")
495
+ li = Element.new(:li, nil, 'id' => "fn:#{name}", 'role' => 'doc-endnote')
489
496
  li.children = Marshal.load(Marshal.dump(data.children))
490
497
 
491
498
  para = nil
@@ -520,7 +527,7 @@ module Kramdown
520
527
  if ol.children.empty?
521
528
  ''
522
529
  else
523
- format_as_indented_block_html('div', {class: "footnotes"}, convert(ol, 2), 0)
530
+ format_as_indented_block_html('div', {class: "footnotes", role: "doc-endnotes"}, convert(ol, 2), 0)
524
531
  end
525
532
  end
526
533
 
@@ -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])
@@ -182,12 +182,17 @@ module Kramdown
182
182
  result << inner(el, opts) << "\n"
183
183
  end
184
184
 
185
- HTML_TAGS_WITH_BODY = ['div', 'script', 'iframe', 'textarea']
185
+ HTML_TAGS_WITH_BODY = ['div', 'script', 'iframe', 'textarea', 'th', 'td']
186
+
187
+ HTML_ELEMENT_TYPES = [:entity, :text, :html_element].freeze
188
+ private_constant :HTML_ELEMENT_TYPES
186
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
@@ -517,7 +517,7 @@ module Kramdown
517
517
  8194 => ['\hskip .5em\relax'],
518
518
  8195 => ['\quad'],
519
519
  } # :nodoc:
520
- ENTITY_CONV_TABLE.each_value {|v| v[0] = "{}#{v[0]}" }
520
+ ENTITY_CONV_TABLE.each_value {|v| v[0] = "#{v[0]}{}" }
521
521
 
522
522
  def entity_to_latex(entity)
523
523
  text, package = ENTITY_CONV_TABLE[entity.code_point]
@@ -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