kramdown 0.11.0 → 0.12.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 (94) hide show
  1. data/CONTRIBUTERS +1 -1
  2. data/ChangeLog +532 -0
  3. data/README +22 -12
  4. data/Rakefile +9 -8
  5. data/VERSION +1 -1
  6. data/benchmark/benchmark.sh +61 -0
  7. data/benchmark/generate_data.rb +57 -55
  8. data/benchmark/testing.sh +1 -1
  9. data/benchmark/timing.sh +3 -3
  10. data/bin/kramdown +1 -2
  11. data/data/kramdown/document.html +2 -2
  12. data/data/kramdown/document.latex +2 -2
  13. data/doc/default.scss.css +6 -1
  14. data/doc/default.template +1 -1
  15. data/doc/documentation.page +1 -1
  16. data/doc/index.page +9 -7
  17. data/doc/installation.page +2 -3
  18. data/doc/links.markdown +1 -1
  19. data/doc/quickref.page +19 -19
  20. data/doc/syntax.page +117 -98
  21. data/doc/tests.page +8 -7
  22. data/lib/kramdown/compatibility.rb +2 -1
  23. data/lib/kramdown/converter.rb +5 -7
  24. data/lib/kramdown/converter/base.rb +87 -32
  25. data/lib/kramdown/converter/html.rb +134 -122
  26. data/lib/kramdown/converter/kramdown.rb +24 -25
  27. data/lib/kramdown/converter/latex.rb +65 -55
  28. data/lib/kramdown/document.rb +487 -42
  29. data/lib/kramdown/error.rb +3 -0
  30. data/lib/kramdown/options.rb +83 -28
  31. data/lib/kramdown/parser.rb +5 -5
  32. data/lib/kramdown/parser/base.rb +55 -13
  33. data/lib/kramdown/parser/html.rb +83 -71
  34. data/lib/kramdown/parser/kramdown.rb +73 -54
  35. data/lib/kramdown/parser/kramdown/abbreviation.rb +17 -12
  36. data/lib/kramdown/parser/kramdown/autolink.rb +2 -3
  37. data/lib/kramdown/parser/kramdown/blank_line.rb +1 -1
  38. data/lib/kramdown/parser/kramdown/block_boundary.rb +2 -2
  39. data/lib/kramdown/parser/kramdown/blockquote.rb +2 -2
  40. data/lib/kramdown/parser/kramdown/codeblock.rb +5 -2
  41. data/lib/kramdown/parser/kramdown/codespan.rb +1 -2
  42. data/lib/kramdown/parser/kramdown/emphasis.rb +1 -1
  43. data/lib/kramdown/parser/kramdown/escaped_chars.rb +1 -1
  44. data/lib/kramdown/parser/kramdown/extensions.rb +204 -0
  45. data/lib/kramdown/parser/kramdown/footnote.rb +7 -7
  46. data/lib/kramdown/parser/kramdown/header.rb +4 -2
  47. data/lib/kramdown/parser/kramdown/horizontal_rule.rb +1 -1
  48. data/lib/kramdown/parser/kramdown/html.rb +39 -45
  49. data/lib/kramdown/parser/kramdown/link.rb +19 -29
  50. data/lib/kramdown/parser/kramdown/list.rb +13 -13
  51. data/lib/kramdown/parser/kramdown/math.rb +1 -1
  52. data/lib/kramdown/parser/kramdown/paragraph.rb +5 -4
  53. data/lib/kramdown/parser/kramdown/smart_quotes.rb +1 -1
  54. data/lib/kramdown/parser/kramdown/table.rb +51 -12
  55. data/lib/kramdown/parser/markdown.rb +69 -0
  56. data/lib/kramdown/utils.rb +2 -2
  57. data/lib/kramdown/utils/entities.rb +10 -1
  58. data/lib/kramdown/utils/html.rb +22 -11
  59. data/lib/kramdown/utils/ordered_hash.rb +44 -40
  60. data/lib/kramdown/version.rb +1 -1
  61. data/man/man1/kramdown.1 +31 -4
  62. data/test/testcases/block/08_list/item_ial.html +1 -1
  63. data/test/testcases/block/11_ial/nested.html +11 -0
  64. data/test/testcases/block/11_ial/nested.text +15 -0
  65. data/test/testcases/block/13_definition_list/item_ial.html +1 -1
  66. data/test/testcases/block/14_table/escaping.html +52 -0
  67. data/test/testcases/block/14_table/escaping.text +19 -0
  68. data/test/testcases/block/14_table/simple.html.19 +139 -0
  69. data/test/testcases/block/14_table/simple.text +1 -1
  70. data/test/testcases/block/15_math/normal.html +13 -13
  71. data/test/testcases/block/16_toc/{no_toc_depth.html → no_toc.html} +0 -0
  72. data/test/testcases/block/16_toc/{no_toc_depth.options → no_toc.options} +0 -0
  73. data/test/testcases/block/16_toc/{no_toc_depth.text → no_toc.text} +0 -0
  74. data/test/testcases/block/16_toc/{toc_depth_2.html → toc_levels.html} +4 -4
  75. data/test/testcases/block/16_toc/toc_levels.options +1 -0
  76. data/test/testcases/block/16_toc/{toc_depth_2.text → toc_levels.text} +0 -0
  77. data/test/testcases/span/escaped_chars/normal.html +4 -0
  78. data/test/testcases/span/escaped_chars/normal.text +4 -0
  79. data/test/testcases/span/ial/simple.html +1 -1
  80. data/test/testcases/span/math/normal.html +2 -2
  81. metadata +20 -25
  82. data/benchmark/historic-jruby-1.4.0.dat +0 -7
  83. data/benchmark/historic-ruby-1.8.6.dat +0 -7
  84. data/benchmark/historic-ruby-1.8.7.dat +0 -7
  85. data/benchmark/historic-ruby-1.9.1p243.dat +0 -7
  86. data/benchmark/historic-ruby-1.9.2dev.dat +0 -7
  87. data/benchmark/static-jruby-1.4.0.dat +0 -7
  88. data/benchmark/static-ruby-1.8.6.dat +0 -7
  89. data/benchmark/static-ruby-1.8.7.dat +0 -7
  90. data/benchmark/static-ruby-1.9.1p243.dat +0 -7
  91. data/benchmark/static-ruby-1.9.2dev.dat +0 -7
  92. data/lib/kramdown/parser/kramdown/attribute_list.rb +0 -111
  93. data/lib/kramdown/parser/kramdown/extension.rb +0 -116
  94. data/test/testcases/block/16_toc/toc_depth_2.options +0 -1
@@ -20,7 +20,7 @@
20
20
  #++
21
21
  #
22
22
 
23
- require 'kramdown/parser/kramdown/attribute_list'
23
+ require 'kramdown/parser/kramdown/extensions'
24
24
  require 'kramdown/parser/kramdown/blank_line'
25
25
  require 'kramdown/parser/kramdown/codeblock'
26
26
 
@@ -36,8 +36,8 @@ module Kramdown
36
36
 
37
37
  el = Element.new(:footnote_def)
38
38
  parse_blocks(el, @src[2].gsub(INDENT, ''))
39
- warning("Duplicate footnote name '#{@src[1]}' - overwriting") if @doc.parse_infos[:footnotes][@src[1]]
40
- (@doc.parse_infos[:footnotes][@src[1]] = {})[:content] = el
39
+ warning("Duplicate footnote name '#{@src[1]}' - overwriting") if @footnotes[@src[1]]
40
+ (@footnotes[@src[1]] = {})[:content] = el
41
41
  @tree.children << Element.new(:eob, :footnote_def)
42
42
  true
43
43
  end
@@ -49,14 +49,14 @@ module Kramdown
49
49
  # Parse the footnote marker at the current location.
50
50
  def parse_footnote_marker
51
51
  @src.pos += @src.matched_size
52
- fn_def = @doc.parse_infos[:footnotes][@src[1]]
52
+ fn_def = @footnotes[@src[1]]
53
53
  if fn_def
54
- valid = fn_def[:marker] && fn_def[:marker].options[:stack][0..-2].zip(fn_def[:marker].options[:stack][1..-1]).all? do |par, child|
54
+ valid = fn_def[:marker] && fn_def[:stack][0..-2].zip(fn_def[:stack][1..-1]).all? do |par, child|
55
55
  par.children.include?(child)
56
56
  end
57
57
  if !fn_def[:marker] || !valid
58
- fn_def[:marker] = Element.new(:footnote, nil, nil, :name => @src[1])
59
- fn_def[:marker].options[:stack] = [@stack.map {|s| s.first}, @tree, fn_def[:marker]].flatten.compact
58
+ fn_def[:marker] = Element.new(:footnote, fn_def[:content], nil, :name => @src[1])
59
+ fn_def[:stack] = [@stack.map {|s| s.first}, @tree, fn_def[:marker]].flatten.compact
60
60
  @tree.children << fn_def[:marker]
61
61
  else
62
62
  warning("Footnote marker '#{@src[1]}' already appeared in document, ignoring newly found marker")
@@ -34,7 +34,8 @@ module Kramdown
34
34
  return false if !after_block_boundary?
35
35
 
36
36
  @src.pos += @src.matched_size
37
- text, id, level = @src[1].strip, @src[2], @src[3]
37
+ text, id, level = @src[1], @src[2], @src[3]
38
+ text.strip!
38
39
  el = new_block_el(:header, nil, nil, :level => (level == '-' ? 2 : 1), :raw_text => text)
39
40
  add_text(text, el)
40
41
  el.attr['id'] = id if id
@@ -52,7 +53,8 @@ module Kramdown
52
53
  return false if !after_block_boundary?
53
54
 
54
55
  result = @src.scan(ATX_HEADER_MATCH)
55
- level, text, id = @src[1], @src[2].strip, @src[3]
56
+ level, text, id = @src[1], @src[2], @src[3]
57
+ text.strip!
56
58
  el = new_block_el(:header, nil, nil, :level => level.length, :raw_text => text)
57
59
  add_text(text, el)
58
60
  el.attr['id'] = id if id
@@ -24,7 +24,7 @@ module Kramdown
24
24
  module Parser
25
25
  class Kramdown
26
26
 
27
- HR_START = /^#{OPT_SPACE}(\*|-|_)[ \t]*\1[ \t]*\1[ \t]*(\1|[ \t])*\n/
27
+ HR_START = /^#{OPT_SPACE}(\*|-|_)[ \t]*\1[ \t]*\1(\1|[ \t])*\n/
28
28
 
29
29
  # Parse the horizontal rule at the current location.
30
30
  def parse_horizontal_rule
@@ -28,75 +28,68 @@ module Kramdown
28
28
 
29
29
  include Kramdown::Parser::Html::Parser
30
30
 
31
+ # Mapping of markdown attribute value to content model. I.e. :raw when "0", :default when "1"
32
+ # (use default content model for the HTML element), :span when "span", :block when block and
33
+ # for everything else +nil+ is returned.
34
+ HTML_MARKDOWN_ATTR_MAP = {"0" => :raw, "1" => :default, "span" => :span, "block" => :block}
35
+
36
+ TRAILING_WHITESPACE = /[ \t]*\n/
37
+
31
38
  def handle_kramdown_html_tag(el, closed)
32
- parse_type = if @tree.type != :html_element || @tree.options[:parse_type] != :raw
33
- (@doc.options[:parse_block_html] ? HTML_PARSE_AS[el.value] : :raw)
34
- else
35
- :raw
36
- end
37
- if val = html_parse_type(el.attr.delete('markdown'))
38
- parse_type = (val == :default ? HTML_PARSE_AS[el.value] : val)
39
+ el.options[:ial] = @block_ial if @block_ial
40
+
41
+ content_model = if @tree.type != :html_element || @tree.options[:content_model] != :raw
42
+ (@options[:parse_block_html] ? HTML_CONTENT_MODEL[el.value] : :raw)
43
+ else
44
+ :raw
45
+ end
46
+ if val = HTML_MARKDOWN_ATTR_MAP[el.attr.delete('markdown')]
47
+ content_model = (val == :default ? HTML_CONTENT_MODEL[el.value] : val)
39
48
  end
40
49
 
41
- @src.scan(/[ \t]*\n/) if parse_type == :block
42
- el.options[:parse_type] = parse_type
50
+ @src.scan(TRAILING_WHITESPACE) if content_model == :block
51
+ el.options[:content_model] = content_model
43
52
 
44
53
  if !closed
45
- if parse_type == :block
46
- end_tag_found = parse_blocks(el)
47
- if !end_tag_found
54
+ if content_model == :block
55
+ if !parse_blocks(el)
48
56
  warning("Found no end tag for '#{el.value}' - auto-closing it")
49
57
  end
50
- elsif parse_type == :span
58
+ elsif content_model == :span
51
59
  curpos = @src.pos
52
60
  if result = @src.scan_until(/(?=<\/#{el.value}\s*>)/m)
53
61
  add_text(extract_string(curpos...@src.pos, @src), el)
54
62
  @src.scan(HTML_TAG_CLOSE_RE)
55
63
  else
56
- add_text(@src.scan(/.*/m), el)
64
+ add_text(@src.rest, el)
65
+ @src.terminate
57
66
  warning("Found no end tag for '#{el.value}' - auto-closing it")
58
67
  end
59
68
  else
60
69
  parse_raw_html(el, &method(:handle_kramdown_html_tag))
61
70
  end
62
- @src.scan(/[ \t]*\n/) unless (@tree.type == :html_element && @tree.options[:parse_type] == :raw)
63
- end
64
- end
65
-
66
- # Return the HTML parse type defined by the string +val+, i.e. raw when "0", default parsing
67
- # (return value +nil+) when "1", span parsing when "span" and block parsing when "block". If
68
- # +val+ is nil, then the default parsing mode is used.
69
- def html_parse_type(val)
70
- case val
71
- when "0" then :raw
72
- when "1" then :default
73
- when "span" then :span
74
- when "block" then :block
75
- when NilClass then nil
76
- else
77
- warning("Invalid markdown attribute val '#{val}', using default")
78
- nil
71
+ @src.scan(TRAILING_WHITESPACE) unless (@tree.type == :html_element && @tree.options[:content_model] == :raw)
79
72
  end
80
73
  end
81
74
 
82
75
 
83
76
  HTML_BLOCK_START = /^#{OPT_SPACE}<(#{REXML::Parsers::BaseParser::UNAME_STR}|\?|!--|\/)/
84
77
 
85
- # Parse the HTML at the current position as block level HTML.
78
+ # Parse the HTML at the current position as block-level HTML.
86
79
  def parse_block_html
87
80
  if result = @src.scan(HTML_COMMENT_RE)
88
81
  @tree.children << Element.new(:xml_comment, result, nil, :category => :block)
89
- @src.scan(/[ \t]*\n/)
82
+ @src.scan(TRAILING_WHITESPACE)
90
83
  true
91
84
  elsif result = @src.scan(HTML_INSTRUCTION_RE)
92
85
  @tree.children << Element.new(:xml_pi, result, nil, :category => :block)
93
- @src.scan(/[ \t]*\n/)
86
+ @src.scan(TRAILING_WHITESPACE)
94
87
  true
95
88
  else
96
89
  if result = @src.check(/^#{OPT_SPACE}#{HTML_TAG_RE}/) && !HTML_SPAN_ELEMENTS.include?(@src[1])
97
90
  @src.pos += @src.matched_size
98
91
  handle_html_start_tag(&method(:handle_kramdown_html_tag))
99
- Kramdown::Parser::Html::ElementConverter.new(@doc).process(@tree.children.last) if @doc.options[:html_to_native]
92
+ Kramdown::Parser::Html::ElementConverter.convert(@root, @tree.children.last) if @options[:html_to_native]
100
93
  true
101
94
  elsif result = @src.check(/^#{OPT_SPACE}#{HTML_TAG_CLOSE_RE}/) && !HTML_SPAN_ELEMENTS.include?(@src[1])
102
95
  name = @src[1]
@@ -117,7 +110,7 @@ module Kramdown
117
110
 
118
111
  HTML_SPAN_START = /<(#{REXML::Parsers::BaseParser::UNAME_STR}|\?|!--|\/)/
119
112
 
120
- # Parse the HTML at the current position as span level HTML.
113
+ # Parse the HTML at the current position as span-level HTML.
121
114
  def parse_span_html
122
115
  if result = @src.scan(HTML_COMMENT_RE)
123
116
  @tree.children << Element.new(:xml_comment, result, nil, :category => :span)
@@ -128,7 +121,7 @@ module Kramdown
128
121
  add_text(result)
129
122
  elsif result = @src.scan(HTML_TAG_RE)
130
123
  if HTML_BLOCK_ELEMENTS.include?(@src[1])
131
- warning("Found block HTML tag '#{@src[1]}' in span level text")
124
+ warning("Found block HTML tag '#{@src[1]}' in span-level text")
132
125
  add_text(result)
133
126
  return
134
127
  end
@@ -137,20 +130,20 @@ module Kramdown
137
130
  attrs = Utils::OrderedHash.new
138
131
  @src[2].scan(HTML_ATTRIBUTE_RE).each {|name,sep,val| attrs[name] = val.gsub(/\n+/, ' ')}
139
132
 
140
- do_parsing = (HTML_PARSE_AS_RAW.include?(@src[1]) || @tree.options[:parse_type] == :raw ? false : @doc.options[:parse_span_html])
141
- if val = html_parse_type(attrs.delete('markdown'))
133
+ do_parsing = (HTML_CONTENT_MODEL[@src[1]] == :raw || @tree.options[:content_model] == :raw ? false : @options[:parse_span_html])
134
+ if val = HTML_MARKDOWN_ATTR_MAP[attrs.delete('markdown')]
142
135
  if val == :block
143
- warning("Cannot use block level parsing in span level HTML tag - using default mode")
136
+ warning("Cannot use block-level parsing in span-level HTML tag - using default mode")
144
137
  elsif val == :span
145
138
  do_parsing = true
146
139
  elsif val == :default
147
- do_parsing = !HTML_PARSE_AS_RAW.include?(@src[1])
140
+ do_parsing = HTML_CONTENT_MODEL[@src[1]] != :raw
148
141
  elsif val == :raw
149
142
  do_parsing = false
150
143
  end
151
144
  end
152
145
 
153
- el = Element.new(:html_element, @src[1], attrs, :category => :span, :parse_type => (do_parsing ? :span : :raw))
146
+ el = Element.new(:html_element, @src[1], attrs, :category => :span, :content_model => (do_parsing ? :span : :raw))
154
147
  @tree.children << el
155
148
  stop_re = /<\/#{Regexp.escape(@src[1])}\s*>/
156
149
  if !@src[4] && HTML_ELEMENTS_WITHOUT_BODY.include?(el.value)
@@ -160,12 +153,13 @@ module Kramdown
160
153
  @src.scan(stop_re)
161
154
  else
162
155
  warning("Found no end tag for '#{el.value}' - auto-closing it")
163
- add_text(@src.scan(/.*/m), el)
156
+ add_text(@src.rest, el)
157
+ @src.terminate
164
158
  end
165
159
  end
166
- Kramdown::Parser::Html::ElementConverter.new(@doc).process(el) if @doc.options[:html_to_native]
160
+ Kramdown::Parser::Html::ElementConverter.convert(@root, el) if @options[:html_to_native]
167
161
  else
168
- add_text(@src.scan(/./))
162
+ add_text(@src.getch)
169
163
  end
170
164
  end
171
165
  define_parser(:span_html, HTML_SPAN_START, '<')
@@ -33,8 +33,8 @@ module Kramdown
33
33
  def parse_link_definition
34
34
  @src.pos += @src.matched_size
35
35
  link_id, link_url, link_title = @src[1].downcase, @src[2] || @src[3], @src[5]
36
- warning("Duplicate link ID '#{link_id}' - overwriting") if @doc.parse_infos[:link_defs][link_id]
37
- @doc.parse_infos[:link_defs][link_id] = [link_url, link_title]
36
+ warning("Duplicate link ID '#{link_id}' - overwriting") if @link_defs[link_id]
37
+ @link_defs[link_id] = [link_url, link_title]
38
38
  @tree.children << Element.new(:eob, :link_def)
39
39
  true
40
40
  end
@@ -55,7 +55,8 @@ module Kramdown
55
55
  @tree.children << el
56
56
  end
57
57
 
58
- LINK_TEXT_BRACKET_RE = /\\\[|\\\]|\[|\]/
58
+ LINK_BRACKET_STOP_RE = /(\])|!?\[/
59
+ LINK_PAREN_STOP_RE = /(\()|(\))|\s(?=['"])/
59
60
  LINK_INLINE_ID_RE = /\s*?\[(#{LINK_ID_CHARS}+)?\]/
60
61
  LINK_INLINE_TITLE_RE = /\s*?(["'])(.+?)\1\s*?\)/
61
62
  LINK_START = /!?\[(?=[^^])/
@@ -75,15 +76,9 @@ module Kramdown
75
76
  end
76
77
  el = Element.new(link_type)
77
78
 
78
- stop_re = /\]|!?\[/
79
79
  count = 1
80
- found = parse_spans(el, stop_re) do
81
- case @src.matched
82
- when "[", "!["
83
- count += 1
84
- when "]"
85
- count -= 1
86
- end
80
+ found = parse_spans(el, LINK_BRACKET_STOP_RE) do
81
+ count = count + (@src[1] ? -1 : 1)
87
82
  count - el.children.select {|c| c.type == :img}.size == 0
88
83
  end
89
84
  if !found || (link_type == :a && el.children.empty?)
@@ -92,17 +87,13 @@ module Kramdown
92
87
  return
93
88
  end
94
89
  alt_text = extract_string(reset_pos...@src.pos, @src)
95
- conv_link_id = alt_text.gsub(/(\s|\n)+/m, ' ').gsub(LINK_ID_NON_CHARS, '').downcase
96
- @src.scan(stop_re)
90
+ @src.scan(LINK_BRACKET_STOP_RE)
97
91
 
98
92
  # reference style link or no link url
99
93
  if @src.scan(LINK_INLINE_ID_RE) || !@src.check(/\(/)
100
- link_id = (@src[1] || conv_link_id).downcase
101
- if link_id.empty?
102
- @src.pos = reset_pos
103
- add_text(result)
104
- elsif @doc.parse_infos[:link_defs].has_key?(link_id)
105
- add_link(el, @doc.parse_infos[:link_defs][link_id].first, @doc.parse_infos[:link_defs][link_id].last, alt_text)
94
+ link_id = (@src[1] || alt_text.gsub(/(\s|\n)+/, ' ').gsub(LINK_ID_NON_CHARS, '')).downcase
95
+ if @link_defs.has_key?(link_id)
96
+ add_link(el, @link_defs[link_id].first, @link_defs[link_id].last, alt_text)
106
97
  else
107
98
  warning("No link definition for link ID '#{link_id}' found")
108
99
  @src.pos = reset_pos
@@ -120,21 +111,20 @@ module Kramdown
120
111
  end
121
112
  else
122
113
  link_url = ''
123
- re = /\(|\)|\s(?=['"])/
124
114
  nr_of_brackets = 0
125
- while temp = @src.scan_until(re)
126
- link_url += temp
127
- case @src.matched
128
- when /\s/
129
- break
130
- when '('
131
- nr_of_brackets += 1
132
- when ')'
115
+ while temp = @src.scan_until(LINK_PAREN_STOP_RE)
116
+ link_url << temp
117
+ if @src[2]
133
118
  nr_of_brackets -= 1
134
119
  break if nr_of_brackets == 0
120
+ elsif @src[1]
121
+ nr_of_brackets += 1
122
+ else
123
+ break
135
124
  end
136
125
  end
137
- link_url = link_url[1..-2].strip
126
+ link_url = link_url[1..-2]
127
+ link_url.strip!
138
128
 
139
129
  if nr_of_brackets == 0
140
130
  add_link(el, link_url, nil, alt_text)
@@ -23,7 +23,7 @@
23
23
  require 'kramdown/parser/kramdown/blank_line'
24
24
  require 'kramdown/parser/kramdown/eob'
25
25
  require 'kramdown/parser/kramdown/horizontal_rule'
26
- require 'kramdown/parser/kramdown/attribute_list'
26
+ require 'kramdown/parser/kramdown/extensions'
27
27
 
28
28
  module Kramdown
29
29
  module Parser
@@ -34,12 +34,12 @@ module Kramdown
34
34
  # Used for parsing the first line of a list item or a definition, i.e. the line with list item
35
35
  # marker or the definition marker.
36
36
  def parse_first_list_line(indentation, content)
37
- if content =~ LIST_ITEM_IAL
37
+ if content =~ self.class::LIST_ITEM_IAL
38
38
  indentation = 4
39
39
  else
40
40
  while content =~ /^ *\t/
41
41
  temp = content.scan(/^ */).first.length + indentation
42
- content.sub!(/^( *)(\t+)/) {$1 + " "*(4 - (temp % 4)) + " "*($2.length - 1)*4}
42
+ content.sub!(/^( *)(\t+)/) {$1 << " "*(4 - (temp % 4) + ($2.length - 1)*4)}
43
43
  end
44
44
  indentation += content.scan(/^ */).first.length
45
45
  end
@@ -77,8 +77,8 @@ module Kramdown
77
77
  item.value, indentation, content_re, lazy_re, indent_re = parse_first_list_line(@src[1].length, @src[2])
78
78
  list.children << item
79
79
 
80
- item.value.sub!(/^#{IAL_SPAN_START}\s*/) do |match|
81
- parse_attribute_list($~[1], item.options[:ial] ||= {})
80
+ item.value.sub!(/^#{self.class::IAL_SPAN_START}\s*/) do |match|
81
+ parse_attribute_list($1, item.options[:ial] ||= {})
82
82
  ''
83
83
  end
84
84
 
@@ -87,7 +87,7 @@ module Kramdown
87
87
  nested_list_found = (item.value =~ LIST_START)
88
88
  last_is_blank = false
89
89
  elsif (result = @src.scan(content_re)) || (!last_is_blank && (result = @src.scan(lazy_re)))
90
- result.sub!(/^(\t+)/) { " "*4*($1 ? $1.length : 0) }
90
+ result.sub!(/^(\t+)/) { " "*($1 ? 4*$1.length : 0) }
91
91
  result.sub!(indent_re, '')
92
92
  if !nested_list_found && result =~ LIST_START
93
93
  item.value << "^\n"
@@ -123,7 +123,7 @@ module Kramdown
123
123
  (it == list.children.last && it.children.length == 2 && !eob_found)) &&
124
124
  (list.children.last != it || list.children.size == 1 ||
125
125
  list.children[0..-2].any? {|cit| cit.children.first.type != :p || cit.children.first.options[:transparent]})
126
- it.children.first.children.first.value += "\n" if it.children.size > 1 && it.children[1].type != :blank
126
+ it.children.first.children.first.value << "\n" if it.children.size > 1 && it.children[1].type != :blank
127
127
  it.children.first.options[:transparent] = true
128
128
  end
129
129
 
@@ -158,7 +158,7 @@ module Kramdown
158
158
  para = @tree.children.pop
159
159
  first_as_para = true
160
160
  end
161
- para.children.first.value.split("\n").each do |term|
161
+ para.children.first.value.split(/\n/).each do |term|
162
162
  el = Element.new(:dt)
163
163
  el.children << Element.new(:raw_text, term)
164
164
  deflist.children << el
@@ -176,7 +176,7 @@ module Kramdown
176
176
  deflist.children << item
177
177
 
178
178
  item.value.sub!(/^#{IAL_SPAN_START}\s*/) do |match|
179
- parse_attribute_list($~[1], item.options[:ial] ||= {})
179
+ parse_attribute_list($1, item.options[:ial] ||= {})
180
180
  ''
181
181
  end
182
182
 
@@ -186,7 +186,7 @@ module Kramdown
186
186
  elsif @src.check(EOB_MARKER)
187
187
  break
188
188
  elsif (result = @src.scan(content_re)) || (!last_is_blank && (result = @src.scan(lazy_re)))
189
- result.sub!(/^(\t+)/) { " "*4*($1 ? $1.length : 0) }
189
+ result.sub!(/^(\t+)/) { " "*($1 ? 4*$1.length : 0) }
190
190
  result.sub!(indent_re, '')
191
191
  item.value << result
192
192
  first_as_para = false
@@ -214,16 +214,16 @@ module Kramdown
214
214
  last = nil
215
215
  end
216
216
  if it.children.first.type == :p && !it.options.delete(:first_as_para)
217
- it.children.first.children.first.value += "\n" if it.children.size > 1
217
+ it.children.first.children.first.value << "\n" if it.children.size > 1
218
218
  it.children.first.options[:transparent] = true
219
219
  end
220
220
  end
221
221
 
222
222
  if @tree.children.length >= 1 && @tree.children.last.type == :dl
223
- @tree.children[-1].children += deflist.children
223
+ @tree.children[-1].children.concat(deflist.children)
224
224
  elsif @tree.children.length >= 2 && @tree.children[-1].type == :blank && @tree.children[-2].type == :dl
225
225
  @tree.children.pop
226
- @tree.children[-1].children += deflist.children
226
+ @tree.children[-1].children.concat(deflist.children)
227
227
  else
228
228
  @tree.children << deflist
229
229
  end
@@ -40,7 +40,7 @@ module Kramdown
40
40
  @src.pos += @src.matched_size
41
41
  data = @src[2]
42
42
  if before_block_boundary?
43
- @tree.children << new_block_el(:math, data)
43
+ @tree.children << new_block_el(:math, data, nil, :category => :block)
44
44
  true
45
45
  else
46
46
  @src.pos = orig_pos
@@ -21,7 +21,7 @@
21
21
  #
22
22
 
23
23
  require 'kramdown/parser/kramdown/blank_line'
24
- require 'kramdown/parser/kramdown/attribute_list'
24
+ require 'kramdown/parser/kramdown/extensions'
25
25
  require 'kramdown/parser/kramdown/eob'
26
26
  require 'kramdown/parser/kramdown/list'
27
27
  require 'kramdown/parser/kramdown/html'
@@ -39,12 +39,13 @@ module Kramdown
39
39
 
40
40
  # Parse the paragraph at the current location.
41
41
  def parse_paragraph
42
- result = @src.scan(PARAGRAPH_MATCH)
42
+ result = @src.scan(self.class::PARAGRAPH_MATCH).chomp!
43
43
  if @tree.children.last && @tree.children.last.type == :p
44
- @tree.children.last.children.first.value << "\n" << result.chomp
44
+ @tree.children.last.children.first.value << "\n" << result
45
45
  else
46
46
  @tree.children << new_block_el(:p)
47
- @tree.children.last.children << Element.new(@text_type, result.lstrip.chomp)
47
+ result.lstrip!
48
+ @tree.children.last.children << Element.new(@text_type, result)
48
49
  end
49
50
  true
50
51
  end