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
@@ -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.beta2'
13
+ VERSION = '2.3.0'
14
14
 
15
15
  end
@@ -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
@@ -102,6 +109,22 @@ This option can be used to specify the number that is used for the first footnot
102
109
  Default: 1 Used by: HTML converter
103
110
  .RE
104
111
  .TP
112
+ \fB\-\-footnote\-prefix\fP \fIARG\fP
113
+ Prefix used for footnote IDs
114
+ .RS
115
+ .P
116
+ This option can be used to set a prefix for footnote IDs\. This is useful when rendering multiple documents into the same output file to avoid duplicate IDs\. The prefix should only contain characters that are valid in an ID!
117
+ .P
118
+ Default: \[u2018]\[u2019] Used by: HTML
119
+ .RE
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
105
128
  \fB\-\-header\-offset\fP \fIARG\fP
106
129
  Sets the output offset for headers
107
130
  .RS
@@ -198,6 +221,13 @@ If this option is \fBtrue\fP, the RemoveHtmlTags converter removes block HTML ta
198
221
  Default: true Used by: RemoveHtmlTags converter
199
222
  .RE
200
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
201
231
  \fB\-\-[no\-]remove\-span\-html\-tags\fP
202
232
  Remove span HTML tags
203
233
  .RS
@@ -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'
@@ -72,6 +73,7 @@ class TestFiles < Minitest::Test
72
73
  'test/testcases/block/06_codeblock/rouge/multiple.html', # bc of double surrounding <div>
73
74
  'test/testcases/block/06_codeblock/highlighting.html', # bc of span elements inside code element
74
75
  'test/testcases/block/06_codeblock/highlighting-opts.html', # bc of span elements inside code element
76
+ 'test/testcases/block/06_codeblock/guess_lang_css_class.html', # bc of double surrounding <div>
75
77
  'test/testcases/block/12_extension/options3.html', # bc of rouge
76
78
  'test/testcases/block/14_table/empty_tag_in_cell.html', # bc of tidy
77
79
  'test/testcases/block/15_math/mathjax_preview.html', # bc of mathjax preview
@@ -110,14 +112,10 @@ class TestFiles < Minitest::Test
110
112
  end
111
113
 
112
114
  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"
115
+ cmd = "tidy -q --doctype omit -utf8"
116
+ result, error, status = Open3.capture3(cmd, stdin_data: out)
117
+ if status.exitstatus == 2
118
+ raise "Problem using tidy: #{error}"
121
119
  end
122
120
  result
123
121
  end
@@ -134,6 +132,8 @@ class TestFiles < Minitest::Test
134
132
  'test/testcases/span/04_footnote/markers.text', # bc of footnote in header
135
133
  'test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.text',
136
134
  'test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.text',
135
+ 'test/testcases/block/03_paragraph/standalone_image.text', # bc of standalone image
136
+ 'test/testcases/cjk-line-break.text', # latex unicode support
137
137
  ].compact
138
138
  Dir[File.dirname(__FILE__) + '/testcases/**/*.text'].each do |text_file|
139
139
  next if EXCLUDE_LATEX_FILES.any? {|f| text_file =~ /#{f}$/ }
@@ -177,6 +177,9 @@ class TestFiles < Minitest::Test
177
177
  'test/testcases/span/05_html/mark_element.text', # bc of tidy
178
178
  'test/testcases/block/09_html/xml.text', # bc of tidy
179
179
  'test/testcases/span/05_html/xml.text', # bc of tidy
180
+ 'test/testcases/block/03_paragraph/standalone_image.text', # bc of standalone image
181
+ 'test/testcases/cjk-line-break.text',
182
+ 'test/testcases/block/09_html/standalone_image_in_div.html', # bc of standalone image
180
183
  ].compact
181
184
  Dir[File.dirname(__FILE__) + '/testcases/**/*.text'].each do |text_file|
182
185
  next if EXCLUDE_TEXT_FILES.any? {|f| text_file =~ /#{f}$/ }
@@ -209,6 +212,7 @@ class TestFiles < Minitest::Test
209
212
  'test/testcases/block/06_codeblock/whitespace.html', # bc of entity to char conversion
210
213
  'test/testcases/block/06_codeblock/rouge/simple.html', # bc of double surrounding <div>
211
214
  'test/testcases/block/06_codeblock/rouge/multiple.html', # bc of double surrounding <div>
215
+ 'test/testcases/block/06_codeblock/guess_lang_css_class.html', # bc of double surrounding <div>
212
216
  'test/testcases/block/06_codeblock/highlighting.html', # bc of span elements inside code element
213
217
  'test/testcases/block/06_codeblock/highlighting-opts.html', # bc of span elements inside code element
214
218
  'test/testcases/block/11_ial/simple.html', # bc of change of ordering of attributes in header
@@ -218,13 +222,16 @@ class TestFiles < Minitest::Test
218
222
  'test/testcases/block/16_toc/toc_exclude.html', # bc of different attribute ordering
219
223
  'test/testcases/span/autolinks/url_links.html', # bc of quot entity being converted to char
220
224
  'test/testcases/block/14_table/empty_tag_in_cell.html', # bc of tidy
221
- 'test/testcases/block/15_math/mathjax_preview.html', # bc of mathjax preview
222
- 'test/testcases/block/15_math/mathjax_preview_simple.html', # bc of mathjax preview
223
- 'test/testcases/block/15_math/mathjax_preview_as_code.html', # bc of mathjax preview
224
225
  'test/testcases/span/01_link/link_defs_with_ial.html', # bc of attribute ordering
225
226
  'test/testcases/span/05_html/mark_element.html', # bc of tidy
226
227
  'test/testcases/block/09_html/xml.html', # bc of tidy
227
228
  'test/testcases/span/05_html/xml.html', # bc of tidy
229
+ 'test/testcases/block/03_paragraph/standalone_image.html', # bc of standalone image
230
+ 'test/testcases/block/15_math/normal.html', # bc of mathjax and HTML parser
231
+ 'test/testcases/block/15_math/gh_128.html', # bc of mathjax and HTML parser
232
+ 'test/testcases/span/04_footnote/backlink_inline.html', # bc of mathjax
233
+ 'test/testcases/block/09_html/standalone_image_in_div.html', # bc of standalone image
234
+ 'test/testcases/block/09_html/processing_instruction.html', # bc of PI
228
235
  ].compact
229
236
  Dir[File.dirname(__FILE__) + '/testcases/**/*.html'].each do |html_file|
230
237
  next if EXCLUDE_HTML_KD_FILES.any? {|f| html_file =~ /#{f}$/ }
@@ -18,7 +18,7 @@ describe 'location' do
18
18
  def check_element_for_location(element)
19
19
  if (match = /^line-(\d+)/.match(element.attr['class'] || ''))
20
20
  expected_line = match[1].to_i
21
- element.options[:location].must_equal(expected_line)
21
+ assert_equal(expected_line, element.options[:location])
22
22
  end
23
23
  element.children.each do |child|
24
24
  check_element_for_location(child)
@@ -187,7 +187,7 @@ describe 'location' do
187
187
  *[duplicate]: The second definition
188
188
  )
189
189
  doc = Kramdown::Document.new(test_string.strip)
190
- doc.warnings.must_equal ["Duplicate abbreviation ID 'duplicate' on line 4 - overwriting"]
190
+ assert_equal(["Duplicate abbreviation ID 'duplicate' on line 4 - overwriting"], doc.warnings)
191
191
  end
192
192
 
193
193
  it 'handles abbreviations' do