kramdown 0.2.0 → 0.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 (67) hide show
  1. data/ChangeLog +267 -0
  2. data/VERSION +1 -1
  3. data/benchmark/benchmark.rb +2 -1
  4. data/benchmark/generate_data.rb +110 -0
  5. data/benchmark/historic-jruby-1.4.0.dat +7 -0
  6. data/benchmark/historic-ruby-1.8.6.dat +7 -0
  7. data/benchmark/historic-ruby-1.8.7.dat +7 -0
  8. data/benchmark/historic-ruby-1.9.1p243.dat +7 -0
  9. data/benchmark/historic-ruby-1.9.2dev.dat +7 -0
  10. data/benchmark/static-jruby-1.4.0.dat +7 -0
  11. data/benchmark/static-ruby-1.8.6.dat +7 -0
  12. data/benchmark/static-ruby-1.8.7.dat +7 -0
  13. data/benchmark/static-ruby-1.9.1p243.dat +7 -0
  14. data/benchmark/static-ruby-1.9.2dev.dat +7 -0
  15. data/benchmark/testing.sh +1 -1
  16. data/doc/index.page +5 -5
  17. data/doc/installation.page +3 -3
  18. data/doc/quickref.page +3 -3
  19. data/doc/syntax.page +133 -101
  20. data/doc/tests.page +9 -1
  21. data/lib/kramdown/compatibility.rb +34 -0
  22. data/lib/kramdown/converter.rb +26 -8
  23. data/lib/kramdown/document.rb +2 -1
  24. data/lib/kramdown/parser.rb +1 -1192
  25. data/lib/kramdown/parser/kramdown.rb +272 -0
  26. data/lib/kramdown/parser/kramdown/attribute_list.rb +102 -0
  27. data/lib/kramdown/parser/kramdown/autolink.rb +42 -0
  28. data/lib/kramdown/parser/kramdown/blank_line.rb +43 -0
  29. data/lib/kramdown/parser/kramdown/blockquote.rb +42 -0
  30. data/lib/kramdown/parser/kramdown/codeblock.rb +62 -0
  31. data/lib/kramdown/parser/kramdown/codespan.rb +57 -0
  32. data/lib/kramdown/parser/kramdown/emphasis.rb +69 -0
  33. data/lib/kramdown/parser/kramdown/eob.rb +39 -0
  34. data/lib/kramdown/parser/kramdown/escaped_chars.rb +38 -0
  35. data/lib/kramdown/parser/kramdown/extension.rb +65 -0
  36. data/lib/kramdown/parser/kramdown/footnote.rb +72 -0
  37. data/lib/kramdown/parser/kramdown/header.rb +81 -0
  38. data/lib/kramdown/parser/kramdown/horizontal_rule.rb +39 -0
  39. data/lib/kramdown/parser/kramdown/html.rb +253 -0
  40. data/lib/kramdown/{deprecated.rb → parser/kramdown/html_entity.rb} +10 -12
  41. data/lib/kramdown/parser/kramdown/line_break.rb +38 -0
  42. data/lib/kramdown/parser/kramdown/link.rb +153 -0
  43. data/lib/kramdown/parser/kramdown/list.rb +225 -0
  44. data/lib/kramdown/parser/kramdown/paragraph.rb +44 -0
  45. data/lib/kramdown/parser/kramdown/typographic_symbol.rb +48 -0
  46. data/lib/kramdown/version.rb +1 -1
  47. data/test/testcases/block/09_html/comment.html +1 -0
  48. data/test/testcases/block/09_html/comment.text +1 -1
  49. data/test/testcases/block/09_html/content_model/tables.text +2 -2
  50. data/test/testcases/block/09_html/not_parsed.html +10 -0
  51. data/test/testcases/block/09_html/not_parsed.text +9 -0
  52. data/test/testcases/block/09_html/parse_as_raw.html +4 -0
  53. data/test/testcases/block/09_html/parse_as_raw.text +2 -0
  54. data/test/testcases/block/09_html/parse_block_html.html +4 -0
  55. data/test/testcases/block/09_html/parse_block_html.text +3 -0
  56. data/test/testcases/block/09_html/processing_instruction.html +1 -0
  57. data/test/testcases/block/09_html/processing_instruction.text +1 -1
  58. data/test/testcases/block/09_html/simple.html +8 -15
  59. data/test/testcases/block/09_html/simple.text +2 -12
  60. data/test/testcases/span/02_emphasis/normal.html +8 -4
  61. data/test/testcases/span/02_emphasis/normal.text +6 -2
  62. data/test/testcases/span/05_html/markdown_attr.html +2 -1
  63. data/test/testcases/span/05_html/markdown_attr.text +2 -1
  64. data/test/testcases/span/05_html/normal.html +6 -2
  65. data/test/testcases/span/05_html/normal.text +4 -0
  66. metadata +35 -4
  67. data/lib/kramdown/parser/registry.rb +0 -62
@@ -0,0 +1,225 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown.
7
+ #
8
+ # kramdown is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+ #
22
+
23
+ require 'kramdown/parser/kramdown/blank_line'
24
+ require 'kramdown/parser/kramdown/eob'
25
+ require 'kramdown/parser/kramdown/horizontal_rule'
26
+
27
+ module Kramdown
28
+ module Parser
29
+ class Kramdown
30
+
31
+ # Used for parsing the first line of a list item or a definition, i.e. the line with list item
32
+ # marker or the definition marker.
33
+ def parse_first_list_line(indentation, content)
34
+ if content =~ /^\s*\n/
35
+ indentation = 4
36
+ else
37
+ while content =~ /^ *\t/
38
+ temp = content.scan(/^ */).first.length + indentation
39
+ content.sub!(/^( *)(\t+)/) {$1 + " "*(4 - (temp % 4)) + " "*($2.length - 1)*4}
40
+ end
41
+ indentation += content.scan(/^ */).first.length
42
+ end
43
+ content.sub!(/^\s*/, '')
44
+
45
+ indent_re = /^ {#{indentation}}/
46
+ content_re = /^(?:(?:\t| {4}){#{indentation / 4}} {#{indentation % 4}}|(?:\t| {4}){#{indentation / 4 + 1}}).*?\n/
47
+ [content, indentation, content_re, indent_re]
48
+ end
49
+
50
+
51
+ LIST_START_UL = /^(#{OPT_SPACE}[+*-])([\t| ].*?\n)/
52
+ LIST_START_OL = /^(#{OPT_SPACE}\d+\.)([\t| ].*?\n)/
53
+ LIST_START = /#{LIST_START_UL}|#{LIST_START_OL}/
54
+
55
+ # Parse the ordered or unordered list at the current location.
56
+ def parse_list
57
+ if @tree.children.last && @tree.children.last.type == :p # last element must not be a paragraph
58
+ return false
59
+ end
60
+
61
+ type, list_start_re = (@src.check(LIST_START_UL) ? [:ul, LIST_START_UL] : [:ol, LIST_START_OL])
62
+ list = Element.new(type)
63
+
64
+ item = nil
65
+ indent_re = nil
66
+ content_re = nil
67
+ eob_found = false
68
+ nested_list_found = false
69
+ while !@src.eos?
70
+ if @src.check(HR_START)
71
+ break
72
+ elsif @src.scan(list_start_re)
73
+ item = Element.new(:li)
74
+ item.value, indentation, content_re, indent_re = parse_first_list_line(@src[1].length, @src[2])
75
+ list.children << item
76
+
77
+ list_start_re = (type == :ul ? /^( {0,#{[3, indentation - 1].min}}[+*-])([\t| ].*?\n)/ :
78
+ /^( {0,#{[3, indentation - 1].min}}\d+\.)([\t| ].*?\n)/)
79
+ nested_list_found = false
80
+ elsif result = @src.scan(content_re)
81
+ result.sub!(/^(\t+)/) { " "*4*($1 ? $1.length : 0) }
82
+ result.sub!(indent_re, '')
83
+ if !nested_list_found && result =~ LIST_START
84
+ parse_blocks(item, item.value)
85
+ if item.children.length == 1 && item.children.first.type == :p
86
+ item.value = ''
87
+ else
88
+ item.children.clear
89
+ end
90
+ nested_list_found = true
91
+ end
92
+ item.value << result
93
+ elsif result = @src.scan(BLANK_LINE)
94
+ nested_list_found = true
95
+ item.value << result
96
+ elsif @src.scan(EOB_MARKER)
97
+ eob_found = true
98
+ break
99
+ else
100
+ break
101
+ end
102
+ end
103
+
104
+ @tree.children << list
105
+
106
+ last = nil
107
+ list.children.each do |it|
108
+ temp = Element.new(:temp)
109
+ parse_blocks(temp, it.value)
110
+ it.children += temp.children
111
+ it.value = nil
112
+ next if it.children.size == 0
113
+
114
+ if it.children.first.type == :p && (it.children.length < 2 || it.children[1].type != :blank ||
115
+ (it == list.children.last && it.children.length == 2 && !eob_found))
116
+ text = it.children.shift.children.first
117
+ text.value += "\n" if !it.children.empty? && it.children[0].type != :blank
118
+ it.children.unshift(text)
119
+ else
120
+ it.options[:first_is_block] = true
121
+ end
122
+
123
+ if it.children.last.type == :blank
124
+ last = it.children.pop
125
+ else
126
+ last = nil
127
+ end
128
+ end
129
+
130
+ @tree.children << last if !last.nil? && !eob_found
131
+
132
+ true
133
+ end
134
+ define_parser(:list, LIST_START)
135
+
136
+
137
+ DEFINITION_LIST_START = /^(#{OPT_SPACE}:)([\t| ].*?\n)/
138
+
139
+ # Parse the ordered or unordered list at the current location.
140
+ def parse_definition_list
141
+ children = @tree.children
142
+ if !children.last || (children.length == 1 && children.last.type != :p ) ||
143
+ (children.length >= 2 && children[-1].type != :p && (children[-1].type != :blank || children[-1].value != "\n" || children[-2].type != :p))
144
+ return false
145
+ end
146
+
147
+ first_as_para = false
148
+ deflist = Element.new(:dl)
149
+ para = @tree.children.pop
150
+ if para.type == :blank
151
+ para = @tree.children.pop
152
+ first_as_para = true
153
+ end
154
+ para.children.first.value.split("\n").each do |term|
155
+ el = Element.new(:dt)
156
+ el.children << Element.new(:text, term)
157
+ deflist.children << el
158
+ end
159
+
160
+ item = nil
161
+ indent_re = nil
162
+ content_re = nil
163
+ def_start_re = DEFINITION_LIST_START
164
+ while !@src.eos?
165
+ if @src.scan(def_start_re)
166
+ item = Element.new(:dd)
167
+ item.options[:first_as_para] = first_as_para
168
+ item.value, indentation, content_re, indent_re = parse_first_list_line(@src[1].length, @src[2])
169
+ deflist.children << item
170
+
171
+ def_start_re = /^( {0,#{[3, indentation - 1].min}}:)([\t| ].*?\n)/
172
+ first_as_para = false
173
+ elsif result = @src.scan(content_re)
174
+ result.sub!(/^(\t+)/) { " "*4*($1 ? $1.length : 0) }
175
+ result.sub!(indent_re, '')
176
+ item.value << result
177
+ first_as_para = false
178
+ elsif result = @src.scan(BLANK_LINE)
179
+ first_as_para = true
180
+ item.value << result
181
+ else
182
+ break
183
+ end
184
+ end
185
+
186
+ last = nil
187
+ deflist.children.each do |it|
188
+ next if it.type == :dt
189
+
190
+ parse_blocks(it, it.value)
191
+ it.value = nil
192
+ next if it.children.size == 0
193
+
194
+ if it.children.last.type == :blank
195
+ last = it.children.pop
196
+ else
197
+ last = nil
198
+ end
199
+ if it.children.first.type == :p && !it.options.delete(:first_as_para)
200
+ text = it.children.shift.children.first
201
+ text.value += "\n" if !it.children.empty?
202
+ it.children.unshift(text)
203
+ else
204
+ it.options[:first_is_block] = true
205
+ end
206
+ end
207
+
208
+ if @tree.children.length >= 1 && @tree.children.last.type == :dl
209
+ @tree.children[-1].children += deflist.children
210
+ elsif @tree.children.length >= 2 && @tree.children[-1].type == :blank && @tree.children[-2].type == :dl
211
+ @tree.children.pop
212
+ @tree.children[-1].children += deflist.children
213
+ else
214
+ @tree.children << deflist
215
+ end
216
+
217
+ @tree.children << last if !last.nil?
218
+
219
+ true
220
+ end
221
+ define_parser(:definition_list, DEFINITION_LIST_START)
222
+
223
+ end
224
+ end
225
+ end
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown.
7
+ #
8
+ # kramdown is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+ #
22
+
23
+ module Kramdown
24
+ module Parser
25
+ class Kramdown
26
+
27
+ PARAGRAPH_START = /^#{OPT_SPACE}[^ \t].*?\n/
28
+
29
+ # Parse the paragraph at the current location.
30
+ def parse_paragraph
31
+ @src.pos += @src.matched_size
32
+ if @tree.children.last && @tree.children.last.type == :p
33
+ @tree.children.last.children.first.value << "\n" << @src.matched.chomp
34
+ else
35
+ @tree.children << Element.new(:p)
36
+ add_text(@src.matched.lstrip.chomp, @tree.children.last)
37
+ end
38
+ true
39
+ end
40
+ define_parser(:paragraph, PARAGRAPH_START)
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,48 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown.
7
+ #
8
+ # kramdown is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+ #
22
+
23
+ module Kramdown
24
+ module Parser
25
+ class Kramdown
26
+
27
+ TYPOGRAPHIC_SYMS = [['---', :mdash], ['--', :ndash], ['...', :ellipsis],
28
+ ['\\<<', '&lt;&lt;'], ['\\>>', '&gt;&gt;'],
29
+ ['<< ', :laquo_space], [' >>', :raquo_space],
30
+ ['<<', :laquo], ['>>', :raquo]]
31
+ TYPOGRAPHIC_SYMS_SUBST = Hash[*TYPOGRAPHIC_SYMS.flatten]
32
+ TYPOGRAPHIC_SYMS_RE = /#{TYPOGRAPHIC_SYMS.map {|k,v| Regexp.escape(k)}.join('|')}/
33
+
34
+ # Parse the typographic symbols at the current location.
35
+ def parse_typographic_syms
36
+ @src.pos += @src.matched_size
37
+ val = TYPOGRAPHIC_SYMS_SUBST[@src.matched]
38
+ if val.kind_of?(Symbol)
39
+ @tree.children << Element.new(:typographic_sym, val)
40
+ else
41
+ add_text(val.dup)
42
+ end
43
+ end
44
+ define_parser(:typographic_syms, TYPOGRAPHIC_SYMS_RE)
45
+
46
+ end
47
+ end
48
+ end
@@ -23,6 +23,6 @@
23
23
  module Kramdown
24
24
 
25
25
  # The kramdown version.
26
- VERSION = '0.2.0'
26
+ VERSION = '0.3.0'
27
27
 
28
28
  end
@@ -10,3 +10,4 @@
10
10
  Blah
11
11
  Blah
12
12
  -->
13
+ <p>para</p>
@@ -9,4 +9,4 @@ para2
9
9
  <!--
10
10
  Blah
11
11
  Blah
12
- --> these chars are ignored
12
+ --> para
@@ -1,12 +1,12 @@
1
1
  <table class="examples">
2
2
  <tr>
3
- <th>*Usage*</th>
3
+ <th markdown="span">*Usage*</th>
4
4
  <th>
5
5
  Output
6
6
  </th>
7
7
  </tr>
8
8
  <tr>
9
- <td>Some *data*</td>
9
+ <td markdown="span">Some *data*</td>
10
10
  <td>
11
11
  # Some more
12
12
  </td>
@@ -7,8 +7,18 @@ This is some text
7
7
  </div></div>
8
8
 
9
9
  <div>
10
+
10
11
  </div>
11
12
 
12
13
  <div>
13
14
  <p><a href="/">Foo</a></p>
14
15
  </div>
16
+
17
+ <p>This is some
18
+ text</p>
19
+
20
+ <p><a href="http://example.com">http://example.com</a></p>
21
+
22
+ <div>
23
+ &lt;http://example.com&gt;
24
+ </div>
@@ -13,3 +13,12 @@ This is some text
13
13
  <div>
14
14
  <p><a href="/">Foo</a></p>
15
15
  </div>
16
+
17
+ <p>This is some
18
+ text</p>
19
+
20
+ <http://example.com>
21
+
22
+ <div>
23
+ <http://example.com>
24
+ </div>
@@ -24,5 +24,9 @@ This should be output
24
24
  </p> and nothing should be done
25
25
  about it
26
26
  <script>
27
+
28
+
27
29
  </script>
30
+
31
+ &lt;http://example.com&gt;
28
32
  </script>
@@ -26,3 +26,5 @@ about it
26
26
  </not>
27
27
  </p>
28
28
  </script>
29
+
30
+ <http://example.com>
@@ -15,3 +15,7 @@
15
15
  <pre><code>code block with &lt;/div&gt;
16
16
  </code></pre>
17
17
  </div>
18
+
19
+ <div>
20
+ <p>No matching end tag</p>
21
+ </div>
@@ -12,3 +12,6 @@
12
12
  <div>
13
13
  code block with </div>
14
14
  </div>
15
+
16
+ <div>
17
+ No matching end tag
@@ -3,6 +3,7 @@
3
3
  <p>para</p>
4
4
 
5
5
  <? test ?>
6
+ <p>para</p>
6
7
 
7
8
  <p>other</p>
8
9
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  para
4
4
 
5
- <? test ?> ignored characters
5
+ <? test ?> para
6
6
 
7
7
  other
8
8
 
@@ -23,25 +23,17 @@ weiter
23
23
  </div>
24
24
  <div style="&nbsp;"></div>
25
25
  </div>
26
- <div>bar&nbsp;</div>
26
+ <div>
27
+ <p>bar&nbsp;</p>
28
+ </div>
27
29
  </div>
28
30
 
29
31
  <p>para5</p>
30
32
 
31
- <div>id</div>
32
-
33
- <div>id
34
- </div>
35
- test
36
-
37
- <div>hallo<div>test</div>
38
- <p>hallo</p>
39
- </div>
40
-
41
- <div>hallo<div>test
42
- <p>hallo</p>
43
- </div>
33
+ <div>
34
+ <p>id</p>
44
35
  </div>
36
+ <p>test</p>
45
37
 
46
38
  <div>
47
39
  <p>hallo</p>
@@ -52,7 +44,8 @@ weiter
52
44
 
53
45
  <p>para6</p>
54
46
 
55
- <div><div class="clear"></div>
47
+ <div>
48
+ <div class="clear"></div>
56
49
  <p>Another para.</p>
57
50
  </div>
58
51