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.
- data/ChangeLog +267 -0
- data/VERSION +1 -1
- data/benchmark/benchmark.rb +2 -1
- data/benchmark/generate_data.rb +110 -0
- data/benchmark/historic-jruby-1.4.0.dat +7 -0
- data/benchmark/historic-ruby-1.8.6.dat +7 -0
- data/benchmark/historic-ruby-1.8.7.dat +7 -0
- data/benchmark/historic-ruby-1.9.1p243.dat +7 -0
- data/benchmark/historic-ruby-1.9.2dev.dat +7 -0
- data/benchmark/static-jruby-1.4.0.dat +7 -0
- data/benchmark/static-ruby-1.8.6.dat +7 -0
- data/benchmark/static-ruby-1.8.7.dat +7 -0
- data/benchmark/static-ruby-1.9.1p243.dat +7 -0
- data/benchmark/static-ruby-1.9.2dev.dat +7 -0
- data/benchmark/testing.sh +1 -1
- data/doc/index.page +5 -5
- data/doc/installation.page +3 -3
- data/doc/quickref.page +3 -3
- data/doc/syntax.page +133 -101
- data/doc/tests.page +9 -1
- data/lib/kramdown/compatibility.rb +34 -0
- data/lib/kramdown/converter.rb +26 -8
- data/lib/kramdown/document.rb +2 -1
- data/lib/kramdown/parser.rb +1 -1192
- data/lib/kramdown/parser/kramdown.rb +272 -0
- data/lib/kramdown/parser/kramdown/attribute_list.rb +102 -0
- data/lib/kramdown/parser/kramdown/autolink.rb +42 -0
- data/lib/kramdown/parser/kramdown/blank_line.rb +43 -0
- data/lib/kramdown/parser/kramdown/blockquote.rb +42 -0
- data/lib/kramdown/parser/kramdown/codeblock.rb +62 -0
- data/lib/kramdown/parser/kramdown/codespan.rb +57 -0
- data/lib/kramdown/parser/kramdown/emphasis.rb +69 -0
- data/lib/kramdown/parser/kramdown/eob.rb +39 -0
- data/lib/kramdown/parser/kramdown/escaped_chars.rb +38 -0
- data/lib/kramdown/parser/kramdown/extension.rb +65 -0
- data/lib/kramdown/parser/kramdown/footnote.rb +72 -0
- data/lib/kramdown/parser/kramdown/header.rb +81 -0
- data/lib/kramdown/parser/kramdown/horizontal_rule.rb +39 -0
- data/lib/kramdown/parser/kramdown/html.rb +253 -0
- data/lib/kramdown/{deprecated.rb → parser/kramdown/html_entity.rb} +10 -12
- data/lib/kramdown/parser/kramdown/line_break.rb +38 -0
- data/lib/kramdown/parser/kramdown/link.rb +153 -0
- data/lib/kramdown/parser/kramdown/list.rb +225 -0
- data/lib/kramdown/parser/kramdown/paragraph.rb +44 -0
- data/lib/kramdown/parser/kramdown/typographic_symbol.rb +48 -0
- data/lib/kramdown/version.rb +1 -1
- data/test/testcases/block/09_html/comment.html +1 -0
- data/test/testcases/block/09_html/comment.text +1 -1
- data/test/testcases/block/09_html/content_model/tables.text +2 -2
- data/test/testcases/block/09_html/not_parsed.html +10 -0
- data/test/testcases/block/09_html/not_parsed.text +9 -0
- data/test/testcases/block/09_html/parse_as_raw.html +4 -0
- data/test/testcases/block/09_html/parse_as_raw.text +2 -0
- data/test/testcases/block/09_html/parse_block_html.html +4 -0
- data/test/testcases/block/09_html/parse_block_html.text +3 -0
- data/test/testcases/block/09_html/processing_instruction.html +1 -0
- data/test/testcases/block/09_html/processing_instruction.text +1 -1
- data/test/testcases/block/09_html/simple.html +8 -15
- data/test/testcases/block/09_html/simple.text +2 -12
- data/test/testcases/span/02_emphasis/normal.html +8 -4
- data/test/testcases/span/02_emphasis/normal.text +6 -2
- data/test/testcases/span/05_html/markdown_attr.html +2 -1
- data/test/testcases/span/05_html/markdown_attr.text +2 -1
- data/test/testcases/span/05_html/normal.html +6 -2
- data/test/testcases/span/05_html/normal.text +4 -0
- metadata +35 -4
- 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
|
+
['\\<<', '<<'], ['\\>>', '>>'],
|
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
|
data/lib/kramdown/version.rb
CHANGED
@@ -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
|
+
<http://example.com>
|
24
|
+
</div>
|
@@ -23,25 +23,17 @@ weiter
|
|
23
23
|
</div>
|
24
24
|
<div style=" "></div>
|
25
25
|
</div>
|
26
|
-
<div>
|
26
|
+
<div>
|
27
|
+
<p>bar </p>
|
28
|
+
</div>
|
27
29
|
</div>
|
28
30
|
|
29
31
|
<p>para5</p>
|
30
32
|
|
31
|
-
<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
|
47
|
+
<div>
|
48
|
+
<div class="clear"></div>
|
56
49
|
<p>Another para.</p>
|
57
50
|
</div>
|
58
51
|
|