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.
- checksums.yaml +4 -4
- data/CONTRIBUTERS +13 -3
- data/README.md +8 -2
- data/VERSION +1 -1
- data/bin/kramdown +48 -19
- data/lib/kramdown/converter/base.rb +2 -1
- data/lib/kramdown/converter/html.rb +36 -29
- data/lib/kramdown/converter/kramdown.rb +12 -7
- data/lib/kramdown/converter/latex.rb +2 -2
- data/lib/kramdown/converter/math_engine/mathjax.rb +7 -33
- data/lib/kramdown/converter/syntax_highlighter.rb +1 -1
- data/lib/kramdown/converter/syntax_highlighter/rouge.rb +20 -10
- data/lib/kramdown/element.rb +24 -0
- data/lib/kramdown/options.rb +53 -12
- data/lib/kramdown/parser/base.rb +3 -1
- data/lib/kramdown/parser/html.rb +8 -8
- data/lib/kramdown/parser/kramdown.rb +8 -1
- data/lib/kramdown/parser/kramdown/abbreviation.rb +1 -1
- data/lib/kramdown/parser/kramdown/autolink.rb +2 -2
- data/lib/kramdown/parser/kramdown/blank_line.rb +2 -2
- data/lib/kramdown/parser/kramdown/block_boundary.rb +3 -2
- data/lib/kramdown/parser/kramdown/codespan.rb +13 -3
- data/lib/kramdown/parser/kramdown/emphasis.rb +1 -1
- data/lib/kramdown/parser/kramdown/extensions.rb +13 -7
- data/lib/kramdown/parser/kramdown/header.rb +3 -2
- data/lib/kramdown/parser/kramdown/html.rb +4 -10
- data/lib/kramdown/parser/kramdown/link.rb +3 -2
- data/lib/kramdown/parser/kramdown/list.rb +64 -33
- data/lib/kramdown/parser/kramdown/math.rb +1 -1
- data/lib/kramdown/parser/kramdown/paragraph.rb +3 -3
- data/lib/kramdown/parser/kramdown/table.rb +3 -3
- data/lib/kramdown/utils/html.rb +9 -0
- data/lib/kramdown/version.rb +1 -1
- data/man/man1/kramdown.1 +22 -1
- data/test/test_files.rb +27 -18
- data/test/test_location.rb +2 -2
- data/test/test_string_scanner_kramdown.rb +1 -1
- data/test/testcases/block/03_paragraph/standalone_image.html +5 -0
- data/test/testcases/block/03_paragraph/standalone_image.text +3 -0
- data/test/testcases/block/04_header/atx_header.html +6 -0
- data/test/testcases/block/04_header/atx_header.text +6 -0
- data/test/testcases/block/06_codeblock/guess_lang_css_class.html +15 -0
- data/test/testcases/block/06_codeblock/guess_lang_css_class.options +2 -0
- data/test/testcases/block/06_codeblock/guess_lang_css_class.text +13 -0
- data/test/testcases/block/06_codeblock/rouge/multiple.html +1 -1
- data/test/testcases/block/06_codeblock/rouge/simple.html +1 -1
- data/test/testcases/block/09_html/processing_instruction.html +5 -6
- data/test/testcases/block/09_html/standalone_image_in_div.htmlinput +7 -0
- data/test/testcases/block/09_html/standalone_image_in_div.text +8 -0
- data/test/testcases/block/09_html/table.kramdown +8 -0
- data/test/testcases/block/09_html/table.text +7 -0
- data/test/testcases/block/12_extension/options.html +4 -4
- data/test/testcases/block/12_extension/options.text +2 -0
- data/test/testcases/block/12_extension/options2.html +4 -4
- data/test/testcases/block/14_table/table_with_footnote.html +4 -4
- data/test/testcases/block/15_math/gh_128.html +1 -2
- data/test/testcases/block/15_math/normal.html +16 -15
- data/test/testcases/block/16_toc/toc_with_footnotes.html +4 -4
- data/test/testcases/cjk-line-break.html +4 -0
- data/test/testcases/cjk-line-break.options +1 -0
- data/test/testcases/cjk-line-break.text +12 -0
- data/test/testcases/span/02_emphasis/normal.html +4 -0
- data/test/testcases/span/02_emphasis/normal.text +4 -0
- data/test/testcases/span/03_codespan/normal-css-class.html +1 -0
- data/test/testcases/span/03_codespan/normal-css-class.options +2 -0
- data/test/testcases/span/03_codespan/normal-css-class.text +1 -0
- data/test/testcases/span/03_codespan/normal.html +4 -0
- data/test/testcases/span/03_codespan/normal.text +4 -0
- data/test/testcases/span/04_footnote/backlink_inline.html +21 -21
- data/test/testcases/span/04_footnote/backlink_text.html +4 -4
- data/test/testcases/span/04_footnote/footnote_nr.html +6 -6
- data/test/testcases/span/04_footnote/footnote_prefix.html +6 -6
- data/test/testcases/span/04_footnote/inside_footnote.html +9 -9
- data/test/testcases/span/04_footnote/markers.html +16 -16
- data/test/testcases/span/04_footnote/placement.html +4 -4
- data/test/testcases/span/04_footnote/regexp_problem.html +4 -4
- data/test/testcases/span/04_footnote/without_backlink.html +3 -3
- data/test/testcases/span/05_html/normal.html +1 -1
- data/test/testcases/span/abbreviations/abbrev_in_html.html +9 -0
- data/test/testcases/span/abbreviations/abbrev_in_html.text +10 -0
- data/test/testcases/span/abbreviations/in_footnote.html +4 -4
- data/test/testcases/span/math/normal.html +4 -4
- data/test/testcases/span/text_substitutions/entities.html +1 -1
- data/test/testcases/span/text_substitutions/entities.text +1 -1
- metadata +40 -15
- data/test/testcases/block/15_math/mathjax_preview.html +0 -4
- data/test/testcases/block/15_math/mathjax_preview.options +0 -2
- data/test/testcases/block/15_math/mathjax_preview.text +0 -5
- data/test/testcases/block/15_math/mathjax_preview_as_code.html +0 -4
- data/test/testcases/block/15_math/mathjax_preview_as_code.options +0 -3
- data/test/testcases/block/15_math/mathjax_preview_as_code.text +0 -5
- data/test/testcases/block/15_math/mathjax_preview_simple.html +0 -4
- data/test/testcases/block/15_math/mathjax_preview_simple.options +0 -2
- 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!(/
|
|
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
|
|
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
|
-
|
|
96
|
-
|
|
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
|
-
|
|
48
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
129
|
-
|
|
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
|
|
132
|
-
(
|
|
133
|
-
|
|
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
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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 = (
|
|
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}:)(
|
|
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 =
|
|
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
|
-
|
|
225
|
+
it_children = it.children
|
|
226
|
+
next if it_children.empty?
|
|
226
227
|
|
|
227
|
-
last = (
|
|
228
|
+
last = (it_children.last.type == :blank ? it_children.pop : nil)
|
|
228
229
|
|
|
229
|
-
if
|
|
230
|
-
|
|
231
|
-
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
|
|
244
|
+
children << deflist
|
|
243
245
|
end
|
|
244
246
|
|
|
245
|
-
|
|
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
|
|
@@ -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 &&
|
|
40
|
-
last_item_in_para =
|
|
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,
|
|
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
|
data/lib/kramdown/utils/html.rb
CHANGED
|
@@ -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
|
data/lib/kramdown/version.rb
CHANGED
data/man/man1/kramdown.1
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
.\" generated by kramdown
|
|
2
|
-
.TH "KRAMDOWN" "1" "
|
|
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
|
-
|
|
24
|
+
module Rouge
|
|
25
|
+
module Formatters
|
|
26
|
+
class RougeHTMLFormatters < Kramdown::Converter::SyntaxHighlighter::Rouge.formatter_class
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
tag 'rouge_html_formatters'
|
|
26
29
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
114
|
-
result =
|
|
115
|
-
|
|
116
|
-
|
|
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}$/ }
|