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
@@ -8,6 +8,7 @@
8
8
  #
9
9
 
10
10
  require 'kramdown/parser/kramdown/block_boundary'
11
+ require 'rexml/xmltokens'
11
12
 
12
13
  module Kramdown
13
14
  module Parser
@@ -31,7 +32,7 @@ module Kramdown
31
32
  def parse_atx_header
32
33
  return false unless after_block_boundary?
33
34
  text, id = parse_header_contents
34
- text.sub!(/[\t ]#+\z/, '') && text.rstrip!
35
+ text.sub!(/(?<!\\)#+\z/, '') && text.rstrip!
35
36
  return false if text.empty?
36
37
  add_header(@src["level"].length, text, id)
37
38
  true
@@ -40,7 +41,7 @@ module Kramdown
40
41
 
41
42
  protected
42
43
 
43
- HEADER_ID = /[\t ]{#(?<id>[A-Za-z][\w:-]*)}\z/
44
+ HEADER_ID = /[\t ]{#(?<id>#{REXML::XMLTokens::NAME_START_CHAR}#{REXML::XMLTokens::NAME_CHAR}*)}\z/
44
45
 
45
46
  # Returns header text and optional ID.
46
47
  def parse_header_contents
@@ -65,7 +65,7 @@ module Kramdown
65
65
  end
66
66
  end
67
67
 
68
- HTML_BLOCK_START = /^#{OPT_SPACE}<(#{REXML::Parsers::BaseParser::UNAME_STR}|\?|!--|\/)/
68
+ HTML_BLOCK_START = /^#{OPT_SPACE}<(#{REXML::Parsers::BaseParser::UNAME_STR}|!--|\/)/
69
69
 
70
70
  # Parse the HTML at the current position as block-level HTML.
71
71
  def parse_block_html
@@ -74,17 +74,13 @@ module Kramdown
74
74
  @tree.children << Element.new(:xml_comment, result, nil, category: :block, location: line)
75
75
  @src.scan(TRAILING_WHITESPACE)
76
76
  true
77
- elsif (result = @src.scan(HTML_INSTRUCTION_RE))
78
- @tree.children << Element.new(:xml_pi, result, nil, category: :block, location: line)
79
- @src.scan(TRAILING_WHITESPACE)
80
- true
81
77
  else
82
- if @src.check(/^#{OPT_SPACE}#{HTML_TAG_RE}/) && !HTML_SPAN_ELEMENTS.include?(@src[1].downcase)
78
+ if @src.check(/^#{OPT_SPACE}#{HTML_TAG_RE}/o) && !HTML_SPAN_ELEMENTS.include?(@src[1].downcase)
83
79
  @src.pos += @src.matched_size
84
80
  handle_html_start_tag(line, &method(:handle_kramdown_html_tag))
85
81
  Kramdown::Parser::Html::ElementConverter.convert(@root, @tree.children.last) if @options[:html_to_native]
86
82
  true
87
- elsif @src.check(/^#{OPT_SPACE}#{HTML_TAG_CLOSE_RE}/) && !HTML_SPAN_ELEMENTS.include?(@src[1].downcase)
83
+ elsif @src.check(/^#{OPT_SPACE}#{HTML_TAG_CLOSE_RE}/o) && !HTML_SPAN_ELEMENTS.include?(@src[1].downcase)
88
84
  name = @src[1].downcase
89
85
 
90
86
  if @tree.type == :html_element && @tree.value == name
@@ -100,15 +96,13 @@ module Kramdown
100
96
  end
101
97
  define_parser(:block_html, HTML_BLOCK_START)
102
98
 
103
- HTML_SPAN_START = /<(#{REXML::Parsers::BaseParser::UNAME_STR}|\?|!--|\/)/
99
+ HTML_SPAN_START = /<(#{REXML::Parsers::BaseParser::UNAME_STR}|!--|\/)/
104
100
 
105
101
  # Parse the HTML at the current position as span-level HTML.
106
102
  def parse_span_html
107
103
  line = @src.current_line_number
108
104
  if (result = @src.scan(HTML_COMMENT_RE))
109
105
  @tree.children << Element.new(:xml_comment, result, nil, category: :span, location: line)
110
- elsif (result = @src.scan(HTML_INSTRUCTION_RE))
111
- @tree.children << Element.new(:xml_pi, result, nil, category: :span, location: line)
112
106
  elsif (result = @src.scan(HTML_TAG_CLOSE_RE))
113
107
  warning("Found invalidly used HTML closing tag for '#{@src[1]}' on line #{line}")
114
108
  add_text(result)
@@ -92,8 +92,9 @@ module Kramdown
92
92
  emit_warning = !@src[1]
93
93
  link_id = normalize_link_id(@src[1] || alt_text)
94
94
  if @link_defs.key?(link_id)
95
- add_link(el, @link_defs[link_id][0], @link_defs[link_id][1], alt_text,
96
- @link_defs[link_id][2] && @link_defs[link_id][2].options[:ial])
95
+ link_def = @link_defs[link_id]
96
+ add_link(el, link_def[0], link_def[1], alt_text,
97
+ link_def[2] && link_def[2].options[:ial])
97
98
  else
98
99
  if emit_warning
99
100
  warning("No link definition for link ID '#{link_id}' found on line #{start_line_number}")
@@ -44,8 +44,10 @@ module Kramdown
44
44
  [content, indentation, *PARSE_FIRST_LIST_LINE_REGEXP_CACHE[indentation]]
45
45
  end
46
46
 
47
- LIST_START_UL = /^(#{OPT_SPACE}[+*-])([\t| ].*?\n)/
48
- LIST_START_OL = /^(#{OPT_SPACE}\d+\.)([\t| ].*?\n)/
47
+ PATTERN_TAIL = /[\t| ].*?\n/
48
+
49
+ LIST_START_UL = /^(#{OPT_SPACE}[+*-])(#{PATTERN_TAIL})/
50
+ LIST_START_OL = /^(#{OPT_SPACE}\d+\.)(#{PATTERN_TAIL})/
49
51
  LIST_START = /#{LIST_START_UL}|#{LIST_START_OL}/
50
52
 
51
53
  # Parse the ordered or unordered list at the current location.
@@ -72,16 +74,12 @@ module Kramdown
72
74
  parse_first_list_line(@src[1].length, @src[2])
73
75
  list.children << item
74
76
 
75
- item.value.sub!(self.class::LIST_ITEM_IAL) do |_match|
77
+ item.value.sub!(self.class::LIST_ITEM_IAL) do
76
78
  parse_attribute_list($1, item.options[:ial] ||= {})
77
79
  ''
78
80
  end
79
81
 
80
- list_start_re = if type == :ul
81
- /^( {0,#{[3, indentation - 1].min}}[+*-])([\t| ].*?\n)/
82
- else
83
- /^( {0,#{[3, indentation - 1].min}}\d+\.)([\t| ].*?\n)/
84
- end
82
+ list_start_re = fetch_pattern(type, indentation)
85
83
  nested_list_found = (item.value =~ LIST_START)
86
84
  last_is_blank = false
87
85
  item.value = [item.value]
@@ -122,22 +120,24 @@ module Kramdown
122
120
 
123
121
  it.children = temp.children
124
122
  it.value = nil
125
- next if it.children.empty?
123
+
124
+ it_children = it.children
125
+ next if it_children.empty?
126
126
 
127
127
  # Handle the case where an EOB marker is inserted by a block IAL for the first paragraph
128
- it.children.delete_at(1) if it.children.first.type == :p &&
129
- it.children.length >= 2 && it.children[1].type == :eob && it.children.first.options[:ial]
128
+ it_children.delete_at(1) if it_children.first.type == :p &&
129
+ it_children.length >= 2 && it_children[1].type == :eob && it_children.first.options[:ial]
130
130
 
131
- if it.children.first.type == :p &&
132
- (it.children.length < 2 || it.children[1].type != :blank ||
133
- (it == list.children.last && it.children.length == 2 && !eob_found)) &&
131
+ if it_children.first.type == :p &&
132
+ (it_children.length < 2 || it_children[1].type != :blank ||
133
+ (it == list.children.last && it_children.length == 2 && !eob_found)) &&
134
134
  (list.children.last != it || list.children.size == 1 ||
135
- list.children[0..-2].any? {|cit| !cit.children.first || cit.children.first.type != :p || cit.children.first.options[:transparent] })
136
- it.children.first.children.first.value << "\n" if it.children.size > 1 && it.children[1].type != :blank
137
- it.children.first.options[:transparent] = true
135
+ list.children[0..-2].any? {|cit| !cit.children.first || cit.children.first.type != :p || cit.children.first.options[:transparent] })
136
+ it_children.first.children.first.value << "\n" if it_children.size > 1 && it_children[1].type != :blank
137
+ it_children.first.options[:transparent] = true
138
138
  end
139
139
 
140
- last = (it.children.last.type == :blank ? it.children.pop : nil)
140
+ last = (it_children.last.type == :blank ? it_children.pop : nil)
141
141
  end
142
142
 
143
143
  @tree.children << last if !last.nil? && !eob_found
@@ -146,7 +146,7 @@ module Kramdown
146
146
  end
147
147
  define_parser(:list, LIST_START)
148
148
 
149
- DEFINITION_LIST_START = /^(#{OPT_SPACE}:)([\t| ].*?\n)/
149
+ DEFINITION_LIST_START = /^(#{OPT_SPACE}:)(#{PATTERN_TAIL})/
150
150
 
151
151
  # Parse the ordered or unordered list at the current location.
152
152
  def parse_definition_list
@@ -196,7 +196,7 @@ module Kramdown
196
196
  ''
197
197
  end
198
198
 
199
- def_start_re = /^( {0,#{[3, indentation - 1].min}}:)([\t| ].*?\n)/
199
+ def_start_re = fetch_pattern(:dl, indentation)
200
200
  first_as_para = false
201
201
  last_is_blank = false
202
202
  elsif @src.check(EOB_MARKER)
@@ -222,32 +222,63 @@ module Kramdown
222
222
 
223
223
  parse_blocks(it, it.value)
224
224
  it.value = nil
225
- next if it.children.empty?
225
+ it_children = it.children
226
+ next if it_children.empty?
226
227
 
227
- last = (it.children.last.type == :blank ? it.children.pop : nil)
228
+ last = (it_children.last.type == :blank ? it_children.pop : nil)
228
229
 
229
- if it.children.first && it.children.first.type == :p && !it.options.delete(:first_as_para)
230
- it.children.first.children.first.value << "\n" if it.children.size > 1
231
- it.children.first.options[:transparent] = true
230
+ if it_children.first && it_children.first.type == :p && !it.options.delete(:first_as_para)
231
+ it_children.first.children.first.value << "\n" if it_children.size > 1
232
+ it_children.first.options[:transparent] = true
232
233
  end
233
234
  end
234
235
 
235
- if @tree.children.length >= 1 && @tree.children.last.type == :dl
236
- @tree.children[-1].children.concat(deflist.children)
237
- elsif @tree.children.length >= 2 && @tree.children[-1].type == :blank &&
238
- @tree.children[-2].type == :dl
239
- @tree.children.pop
240
- @tree.children[-1].children.concat(deflist.children)
236
+ children = @tree.children
237
+ if children.length >= 1 && children.last.type == :dl
238
+ children[-1].children.concat(deflist.children)
239
+ elsif children.length >= 2 && children[-1].type == :blank &&
240
+ children[-2].type == :dl
241
+ children.pop
242
+ children[-1].children.concat(deflist.children)
241
243
  else
242
- @tree.children << deflist
244
+ children << deflist
243
245
  end
244
246
 
245
- @tree.children << last if last
247
+ children << last if last
246
248
 
247
249
  true
248
250
  end
249
251
  define_parser(:definition_list, DEFINITION_LIST_START)
250
252
 
253
+ private
254
+
255
+ # precomputed patterns for indentations 1..4 and fallback expression
256
+ # to compute pattern when indentation is outside the 1..4 range.
257
+ def fetch_pattern(type, indentation)
258
+ if type == :ul
259
+ case indentation
260
+ when 1 then %r/^( {0}[+*-])(#{PATTERN_TAIL})/o
261
+ when 2 then %r/^( {0,1}[+*-])(#{PATTERN_TAIL})/o
262
+ when 3 then %r/^( {0,2}[+*-])(#{PATTERN_TAIL})/o
263
+ else %r/^( {0,3}[+*-])(#{PATTERN_TAIL})/o
264
+ end
265
+ elsif type == :ol
266
+ case indentation
267
+ when 1 then %r/^( {0}\d+\.)(#{PATTERN_TAIL})/o
268
+ when 2 then %r/^( {0,1}\d+\.)(#{PATTERN_TAIL})/o
269
+ when 3 then %r/^( {0,2}\d+\.)(#{PATTERN_TAIL})/o
270
+ else %r/^( {0,3}\d+\.)(#{PATTERN_TAIL})/o
271
+ end
272
+ elsif type == :dl
273
+ case indentation
274
+ when 1 then %r/^( {0}:)(#{PATTERN_TAIL})/o
275
+ when 2 then %r/^( {0,1}:)(#{PATTERN_TAIL})/o
276
+ when 3 then %r/^( {0,2}:)(#{PATTERN_TAIL})/o
277
+ else %r/^( {0,3}:)(#{PATTERN_TAIL})/o
278
+ end
279
+ end
280
+ end
281
+
251
282
  end
252
283
  end
253
284
  end
@@ -21,7 +21,7 @@ module Kramdown
21
21
  if !after_block_boundary?
22
22
  return false
23
23
  elsif @src[1]
24
- @src.scan(/^#{OPT_SPACE}\\/) if @src[3]
24
+ @src.scan(/^#{OPT_SPACE}\\/o) if @src[3]
25
25
  return false
26
26
  end
27
27
 
@@ -36,13 +36,13 @@ module Kramdown
36
36
  result << @src.scan(PARAGRAPH_MATCH)
37
37
  end
38
38
  result.rstrip!
39
- if @tree.children.last && @tree.children.last.type == :p
40
- last_item_in_para = @tree.children.last.children.last
39
+ if (last_child = @tree.children.last) && last_child.type == :p
40
+ last_item_in_para = last_child.children.last
41
41
  if last_item_in_para && last_item_in_para.type == @text_type
42
42
  joiner = (extract_string((pos - 3)...pos, @src) == " \n" ? " \n" : "\n")
43
43
  last_item_in_para.value << joiner << result
44
44
  else
45
- add_text(result, @tree.children.last)
45
+ add_text(result, last_child)
46
46
  end
47
47
  else
48
48
  @tree.children << new_block_el(:p, nil, nil, location: start_line_number)
@@ -81,7 +81,7 @@ module Kramdown
81
81
  cells.concat(l)
82
82
  else
83
83
  delim = (c.value.scan(/`+/).max || '') + '`'
84
- tmp = "#{delim}#{' ' if delim.size > 1}#{c.value}#{' ' if delim.size > 1}#{delim}"
84
+ tmp = +"#{delim}#{' ' if delim.size > 1}#{c.value}#{' ' if delim.size > 1}#{delim}"
85
85
  (cells.empty? ? cells : cells.last) << tmp
86
86
  end
87
87
  end
@@ -132,8 +132,8 @@ module Kramdown
132
132
  pipe_on_line = false
133
133
  end
134
134
  else
135
- break if lines.size > 1 && !pipe_on_line && lines.first !~ /^#{TABLE_PIPE_CHECK}/
136
- pipe_on_line = (lines.size > 1 ? false : pipe_on_line) || (lines.last =~ /^#{TABLE_PIPE_CHECK}/)
135
+ break if lines.size > 1 && !pipe_on_line && lines.first !~ /^#{TABLE_PIPE_CHECK}/o
136
+ pipe_on_line = (lines.size > 1 ? false : pipe_on_line) || (lines.last =~ /^#{TABLE_PIPE_CHECK}/o)
137
137
  end
138
138
  end
139
139
  @src.revert_pos(saved_pos) and return false unless pipe_on_line
@@ -42,6 +42,8 @@ module Kramdown
42
42
 
43
43
  # Return the HTML representation of the attributes +attr+.
44
44
  def html_attributes(attr)
45
+ return '' if attr.empty?
46
+
45
47
  attr.map do |k, v|
46
48
  v.nil? || (k == 'id' && v.strip.empty?) ? '' : " #{k}=\"#{escape_html(v.to_s, :attribute)}\""
47
49
  end.join('')
@@ -68,6 +70,13 @@ module Kramdown
68
70
  str.gsub(ESCAPE_RE_FROM_TYPE[type]) {|m| ESCAPE_MAP[m] || m }
69
71
  end
70
72
 
73
+ REDUNDANT_LINE_BREAK_REGEX = /([\p{Han}\p{Hiragana}\p{Katakana}]+)\n([\p{Han}\p{Hiragana}\p{Katakana}]+)/u
74
+ def fix_cjk_line_break(str)
75
+ while str.gsub!(REDUNDANT_LINE_BREAK_REGEX, '\1\2')
76
+ end
77
+ str
78
+ end
79
+
71
80
  end
72
81
 
73
82
  end
@@ -10,6 +10,6 @@
10
10
  module Kramdown
11
11
 
12
12
  # The kramdown version.
13
- VERSION = '2.0.0'
13
+ VERSION = '2.3.1'
14
14
 
15
15
  end
data/man/man1/kramdown.1 CHANGED
@@ -1,5 +1,5 @@
1
1
  .\" generated by kramdown
2
- .TH "KRAMDOWN" "1" "November 2016"
2
+ .TH "KRAMDOWN" "1" "January 2019"
3
3
  .SH NAME
4
4
  kramdown \- a fast, pure\-Ruby Markdown\-superset converter
5
5
  .SH "SYNOPSIS"
@@ -20,6 +20,13 @@ Specify the input format\. Available input formats: \fIkramdown\fP (this is the
20
20
  \fB\-o\fP \fIFORMAT\fP, \fB\-\-output\fP \fIFORMAT\fP
21
21
  Specify one or more output formats separated by commas: \fIhtml\fP (default), \fIkramdown\fP, \fIlatex\fP, \fIman\fP or \fIremove_html_tags\fP\&\. The converter \fIpdf\fP is available through the \fBkramdown\-converter\-pdf\fP gem\.
22
22
  .TP
23
+ \fB\-x\fP \fIEXT\fP, \fB\-\-extension\fP \fIEXT\fP
24
+ Load one or more extensions\. The name of the extension should not include the \fBkramdown\-\fP prefix, e\.g\. just \fBparser\-gfm\fP\&\. Multiple extensions can be loaded by separating them with commas\.
25
+ .RS
26
+ .P
27
+ Note: This option has to be used before any other options that rely on the extension already being loaded\.
28
+ .RE
29
+ .TP
23
30
  \fB\-\-no\-config\-file\fP
24
31
  Do not read any configuration file\. Default behavior is to check for a configuration file and read it if it exists\.
25
32
  .TP
@@ -111,6 +118,13 @@ This option can be used to set a prefix for footnote IDs\. This is useful when r
111
118
  Default: \[u2018]\[u2019] Used by: HTML
112
119
  .RE
113
120
  .TP
121
+ \fB\-\-forbidden\-inline\-options\fP \fIARG\fP
122
+ Defines the options that may not be set using the {::options} extension
123
+ .RS
124
+ .P
125
+ Default: template Used by: HTML converter
126
+ .RE
127
+ .TP
114
128
  \fB\-\-header\-offset\fP \fIARG\fP
115
129
  Sets the output offset for headers
116
130
  .RS
@@ -207,6 +221,13 @@ If this option is \fBtrue\fP, the RemoveHtmlTags converter removes block HTML ta
207
221
  Default: true Used by: RemoveHtmlTags converter
208
222
  .RE
209
223
  .TP
224
+ \fB\-\-[no\-]remove\-line\-breaks\-for\-cjk\fP
225
+ Specifies whether line breaks should be removed between CJK characters
226
+ .RS
227
+ .P
228
+ Default: false Used by: HTML converter
229
+ .RE
230
+ .TP
210
231
  \fB\-\-[no\-]remove\-span\-html\-tags\fP
211
232
  Remove span HTML tags
212
233
  .RS
data/test/test_files.rb CHANGED
@@ -11,6 +11,7 @@ require 'minitest/autorun'
11
11
  require 'kramdown'
12
12
  require 'yaml'
13
13
  require 'tmpdir'
14
+ require 'open3'
14
15
 
15
16
  begin
16
17
  require 'kramdown/converter/syntax_highlighter/rouge'
@@ -20,16 +21,20 @@ begin
20
21
  end
21
22
 
22
23
  # custom formatter for tests
23
- class RougeHTMLFormatters < Kramdown::Converter::SyntaxHighlighter::Rouge.formatter_class
24
+ module Rouge
25
+ module Formatters
26
+ class RougeHTMLFormatters < Kramdown::Converter::SyntaxHighlighter::Rouge.formatter_class
24
27
 
25
- tag 'rouge_html_formatters'
28
+ tag 'rouge_html_formatters'
26
29
 
27
- def stream(tokens, &b)
28
- yield %(<div class="custom-class">)
29
- super
30
- yield %(</div>)
31
- end
30
+ def stream(tokens, &b)
31
+ yield %(<div class="custom-class">)
32
+ super
33
+ yield %(</div>)
34
+ end
32
35
 
36
+ end
37
+ end
33
38
  end
34
39
  rescue LoadError, SyntaxError, NameError
35
40
  end
@@ -72,6 +77,7 @@ class TestFiles < Minitest::Test
72
77
  'test/testcases/block/06_codeblock/rouge/multiple.html', # bc of double surrounding <div>
73
78
  'test/testcases/block/06_codeblock/highlighting.html', # bc of span elements inside code element
74
79
  'test/testcases/block/06_codeblock/highlighting-opts.html', # bc of span elements inside code element
80
+ 'test/testcases/block/06_codeblock/guess_lang_css_class.html', # bc of double surrounding <div>
75
81
  'test/testcases/block/12_extension/options3.html', # bc of rouge
76
82
  'test/testcases/block/14_table/empty_tag_in_cell.html', # bc of tidy
77
83
  'test/testcases/block/15_math/mathjax_preview.html', # bc of mathjax preview
@@ -110,14 +116,10 @@ class TestFiles < Minitest::Test
110
116
  end
111
117
 
112
118
  def tidy_output(out)
113
- cmd = "tidy -q --doctype omit #{RUBY_VERSION >= '1.9' ? '-utf8' : '-raw'} 2>/dev/null"
114
- result = IO.popen(cmd, 'r+') do |io|
115
- io.write(out)
116
- io.close_write
117
- io.read
118
- end
119
- if $?.exitstatus == 2
120
- raise "Problem using tidy"
119
+ cmd = "tidy -q --doctype omit -utf8"
120
+ result, error, status = Open3.capture3(cmd, stdin_data: out)
121
+ if status.exitstatus == 2
122
+ raise "Problem using tidy: #{error}"
121
123
  end
122
124
  result
123
125
  end
@@ -135,6 +137,7 @@ class TestFiles < Minitest::Test
135
137
  'test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.text',
136
138
  'test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.text',
137
139
  'test/testcases/block/03_paragraph/standalone_image.text', # bc of standalone image
140
+ 'test/testcases/cjk-line-break.text', # latex unicode support
138
141
  ].compact
139
142
  Dir[File.dirname(__FILE__) + '/testcases/**/*.text'].each do |text_file|
140
143
  next if EXCLUDE_LATEX_FILES.any? {|f| text_file =~ /#{f}$/ }
@@ -179,6 +182,9 @@ class TestFiles < Minitest::Test
179
182
  'test/testcases/block/09_html/xml.text', # bc of tidy
180
183
  'test/testcases/span/05_html/xml.text', # bc of tidy
181
184
  'test/testcases/block/03_paragraph/standalone_image.text', # bc of standalone image
185
+ 'test/testcases/cjk-line-break.text',
186
+ 'test/testcases/block/09_html/standalone_image_in_div.html', # bc of standalone image
187
+ 'test/testcases/span/abbreviations/abbrev_in_html.text', # bc of invalid abbr tag in SVG
182
188
  ].compact
183
189
  Dir[File.dirname(__FILE__) + '/testcases/**/*.text'].each do |text_file|
184
190
  next if EXCLUDE_TEXT_FILES.any? {|f| text_file =~ /#{f}$/ }
@@ -211,6 +217,7 @@ class TestFiles < Minitest::Test
211
217
  'test/testcases/block/06_codeblock/whitespace.html', # bc of entity to char conversion
212
218
  'test/testcases/block/06_codeblock/rouge/simple.html', # bc of double surrounding <div>
213
219
  'test/testcases/block/06_codeblock/rouge/multiple.html', # bc of double surrounding <div>
220
+ 'test/testcases/block/06_codeblock/guess_lang_css_class.html', # bc of double surrounding <div>
214
221
  'test/testcases/block/06_codeblock/highlighting.html', # bc of span elements inside code element
215
222
  'test/testcases/block/06_codeblock/highlighting-opts.html', # bc of span elements inside code element
216
223
  'test/testcases/block/11_ial/simple.html', # bc of change of ordering of attributes in header
@@ -220,14 +227,16 @@ class TestFiles < Minitest::Test
220
227
  'test/testcases/block/16_toc/toc_exclude.html', # bc of different attribute ordering
221
228
  'test/testcases/span/autolinks/url_links.html', # bc of quot entity being converted to char
222
229
  'test/testcases/block/14_table/empty_tag_in_cell.html', # bc of tidy
223
- 'test/testcases/block/15_math/mathjax_preview.html', # bc of mathjax preview
224
- 'test/testcases/block/15_math/mathjax_preview_simple.html', # bc of mathjax preview
225
- 'test/testcases/block/15_math/mathjax_preview_as_code.html', # bc of mathjax preview
226
230
  'test/testcases/span/01_link/link_defs_with_ial.html', # bc of attribute ordering
227
231
  'test/testcases/span/05_html/mark_element.html', # bc of tidy
228
232
  'test/testcases/block/09_html/xml.html', # bc of tidy
229
233
  'test/testcases/span/05_html/xml.html', # bc of tidy
230
234
  'test/testcases/block/03_paragraph/standalone_image.html', # bc of standalone image
235
+ 'test/testcases/block/15_math/normal.html', # bc of mathjax and HTML parser
236
+ 'test/testcases/block/15_math/gh_128.html', # bc of mathjax and HTML parser
237
+ 'test/testcases/span/04_footnote/backlink_inline.html', # bc of mathjax
238
+ 'test/testcases/block/09_html/standalone_image_in_div.html', # bc of standalone image
239
+ 'test/testcases/block/09_html/processing_instruction.html', # bc of PI
231
240
  ].compact
232
241
  Dir[File.dirname(__FILE__) + '/testcases/**/*.html'].each do |html_file|
233
242
  next if EXCLUDE_HTML_KD_FILES.any? {|f| html_file =~ /#{f}$/ }