kramdown 2.0.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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}$/ }