maruku 0.2.13 → 0.3.0
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.
- data/bin/maruku +23 -15
- data/bin/maruku0.3 +37 -0
- data/bin/marutest +277 -0
- data/docs/changelog-0.3.html +99 -0
- data/docs/changelog-0.3.md +84 -0
- data/docs/faq.html +46 -0
- data/docs/faq.md +32 -0
- data/docs/index.html +629 -64
- data/docs/markdown_extra2.html +67 -14
- data/docs/markdown_syntax.html +631 -94
- data/docs/markdown_syntax_2.html +152 -0
- data/docs/maruku.html +629 -64
- data/docs/maruku.md +108 -105
- data/docs/proposal.html +362 -55
- data/docs/proposal.md +133 -169
- data/docs/todo.html +30 -0
- data/lib/maruku.rb +13 -3
- data/lib/maruku/errors_management.rb +75 -0
- data/lib/maruku/helpers.rb +164 -0
- data/lib/maruku/html_helper.rb +33 -13
- data/lib/maruku/parse_block.rb +89 -92
- data/lib/maruku/parse_doc.rb +43 -18
- data/lib/maruku/parse_span.rb +17 -46
- data/lib/maruku/parse_span_better.rb +681 -0
- data/lib/maruku/string_utils.rb +17 -10
- data/lib/maruku/structures.rb +62 -35
- data/lib/maruku/structures_iterators.rb +39 -0
- data/lib/maruku/tests/benchmark.rb +12 -4
- data/lib/maruku/tests/new_parser.rb +318 -0
- data/lib/maruku/to_html.rb +113 -44
- data/lib/maruku/to_latex.rb +32 -14
- data/lib/maruku/to_markdown.rb +110 -0
- data/lib/maruku/toc.rb +35 -1
- data/lib/maruku/version.rb +10 -1
- data/lib/test.rb +29 -0
- data/tests/others/escaping.md +6 -4
- data/tests/others/links.md +1 -1
- data/tests/others/lists_after_paragraph.md +44 -0
- data/tests/unittest/abbreviations.md +71 -0
- data/tests/unittest/blank.md +43 -0
- data/tests/unittest/blanks_in_code.md +131 -0
- data/tests/unittest/code.md +64 -0
- data/tests/unittest/code2.md +59 -0
- data/tests/unittest/code3.md +121 -0
- data/tests/unittest/easy.md +36 -0
- data/tests/unittest/email.md +39 -0
- data/tests/unittest/encoding/iso-8859-1.md +9 -0
- data/tests/unittest/encoding/utf-8.md +38 -0
- data/tests/unittest/entities.md +174 -0
- data/tests/unittest/escaping.md +97 -0
- data/tests/unittest/extra_dl.md +81 -0
- data/tests/unittest/extra_header_id.md +96 -0
- data/tests/unittest/extra_table1.md +78 -0
- data/tests/unittest/footnotes.md +120 -0
- data/tests/unittest/headers.md +64 -0
- data/tests/unittest/hrule.md +77 -0
- data/tests/unittest/images.md +114 -0
- data/tests/unittest/inline_html.md +185 -0
- data/tests/unittest/links.md +162 -0
- data/tests/unittest/list1.md +80 -0
- data/tests/unittest/list2.md +75 -0
- data/tests/unittest/list3.md +111 -0
- data/tests/unittest/list4.md +43 -0
- data/tests/unittest/lists.md +262 -0
- data/tests/unittest/lists_after_paragraph.md +280 -0
- data/tests/unittest/lists_ol.md +323 -0
- data/tests/unittest/misc_sw.md +751 -0
- data/tests/unittest/notyet/escape.md +46 -0
- data/tests/unittest/notyet/header_after_par.md +85 -0
- data/tests/unittest/notyet/ticks.md +67 -0
- data/tests/unittest/notyet/triggering.md +210 -0
- data/tests/unittest/one.md +33 -0
- data/tests/unittest/paragraph.md +34 -0
- data/tests/unittest/paragraph_rules/dont_merge_ref.md +60 -0
- data/tests/unittest/paragraph_rules/tab_is_blank.md +43 -0
- data/tests/unittest/paragraphs.md +84 -0
- data/tests/unittest/recover/recover_links.md +32 -0
- data/tests/unittest/references/long_example.md +87 -0
- data/tests/unittest/references/spaces_and_numbers.md +27 -0
- data/tests/unittest/syntax_hl.md +99 -0
- data/tests/unittest/test.md +36 -0
- data/tests/unittest/wrapping.md +88 -0
- data/tests/utf8-files/simple.md +1 -0
- metadata +139 -86
- data/lib/maruku/maruku.rb +0 -50
- data/tests/a.md +0 -10
data/lib/maruku/string_utils.rb
CHANGED
@@ -16,11 +16,19 @@
|
|
16
16
|
# along with Maruku; if not, write to the Free Software
|
17
17
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
18
18
|
|
19
|
+
module MarukuStrings
|
20
|
+
def add_tabs(s,n=1,char="\t")
|
21
|
+
s.split("\n").map{|x| char*n+x }.join("\n")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
class MDElement
|
25
|
+
include MarukuStrings
|
26
|
+
end
|
19
27
|
|
20
28
|
class Maruku
|
21
29
|
|
22
30
|
# Split a string into lines, and chomps the newline
|
23
|
-
def
|
31
|
+
def Maruku.split_lines_old(s)
|
24
32
|
a = []
|
25
33
|
s.each_line do |l|
|
26
34
|
l = l.chomp
|
@@ -28,6 +36,10 @@ class Maruku
|
|
28
36
|
end
|
29
37
|
a
|
30
38
|
end
|
39
|
+
|
40
|
+
def Maruku.split_lines(s)
|
41
|
+
s.split("\n")
|
42
|
+
end
|
31
43
|
|
32
44
|
# This parses email headers. Returns an hash. hash['data'] is the message.
|
33
45
|
def parse_email_headers(s)
|
@@ -121,7 +133,7 @@ class Maruku
|
|
121
133
|
while s[i,1] =~ /\s/; i+=1 end
|
122
134
|
return i
|
123
135
|
else
|
124
|
-
|
136
|
+
tell_user "BUG (my bad): '#{s}' is not a list"
|
125
137
|
0
|
126
138
|
end
|
127
139
|
end
|
@@ -164,15 +176,10 @@ class Maruku
|
|
164
176
|
s[i, s.size-1]
|
165
177
|
end
|
166
178
|
|
167
|
-
|
168
|
-
def debug(s)
|
169
|
-
$stderr.puts s
|
170
|
-
end
|
171
|
-
|
172
179
|
def dbg_describe_ary(a, prefix='')
|
173
180
|
i = 0
|
174
181
|
a.each do |l|
|
175
|
-
|
182
|
+
tell_user "#{prefix} (#{i+=1})##{l}#"
|
176
183
|
end
|
177
184
|
end
|
178
185
|
|
@@ -184,7 +191,7 @@ class Maruku
|
|
184
191
|
# raw html is like PHP Markdown Extra: at most three spaces before
|
185
192
|
return :code if number_of_leading_spaces(l)>=4
|
186
193
|
return :footnote_text if l =~ FootnoteText
|
187
|
-
return :
|
194
|
+
return :ref_definition if l =~ LinkRegex or l=~ IncompleteLink
|
188
195
|
return :abbreviation if l =~ Abbreviation
|
189
196
|
return :definition if l =~ Definition
|
190
197
|
# I had a bug with emails and urls at the beginning of the
|
@@ -244,7 +251,7 @@ class Maruku
|
|
244
251
|
# This regex is taken from BlueCloth sources
|
245
252
|
# Link defs are in the form: ^[id]: \n? url "optional title"
|
246
253
|
LinkRegex = %r{
|
247
|
-
^[ ]*\[(
|
254
|
+
^[ ]*\[([^\]]+)\]: # id = $1
|
248
255
|
[ ]*
|
249
256
|
<?(\S+)>? # url = $2
|
250
257
|
[ ]*
|
data/lib/maruku/structures.rb
CHANGED
@@ -19,7 +19,7 @@
|
|
19
19
|
|
20
20
|
|
21
21
|
# I did not want to have a class for each possible element.
|
22
|
-
# Instead I opted to have the class "MDElement"
|
22
|
+
# Instead I opted to have only the class "MDElement"
|
23
23
|
# that represents eveything in the document (paragraphs, headers, etc).
|
24
24
|
#
|
25
25
|
# You can tell what it is by the variable `node_type`.
|
@@ -44,7 +44,7 @@
|
|
44
44
|
#
|
45
45
|
# @doc.meta[:my_property] # => 'value'
|
46
46
|
#
|
47
|
-
# from whichever MDElement.
|
47
|
+
# from whichever MDElement in the hierarchy.
|
48
48
|
|
49
49
|
class MDElement
|
50
50
|
# XXX List not complete
|
@@ -58,19 +58,74 @@ class MDElement
|
|
58
58
|
# :li :want_my_paragraph
|
59
59
|
# :header: :level
|
60
60
|
# code, inline_code: :raw_code
|
61
|
-
|
61
|
+
attr_reader :meta
|
62
62
|
# reference of containing document (document has list of ref)
|
63
63
|
attr_accessor :doc
|
64
64
|
|
65
|
-
def initialize
|
65
|
+
def initialize(node_type_=:unset, children_=[], meta_={} )
|
66
66
|
super();
|
67
|
-
|
68
|
-
|
69
|
-
|
67
|
+
raise 'children is nil' if not children_
|
68
|
+
raise 'meta is nil' if not meta_
|
69
|
+
|
70
|
+
@children = children_
|
71
|
+
@node_type = node_type_
|
72
|
+
@meta = meta_
|
73
|
+
end
|
74
|
+
|
75
|
+
def ==(o)
|
76
|
+
ok = o.kind_of?(MDElement) &&
|
77
|
+
(self.node_type == o.node_type) &&
|
78
|
+
(self.meta == o.meta) &&
|
79
|
+
(self.children == o.children)
|
80
|
+
ok
|
81
|
+
end
|
82
|
+
|
83
|
+
def inspect(compact=true)
|
84
|
+
if compact
|
85
|
+
i2 = inspect2
|
86
|
+
return i2 if i2
|
87
|
+
end
|
88
|
+
|
89
|
+
"md_el(:%s,%s %s)" %
|
90
|
+
[
|
91
|
+
@node_type,
|
92
|
+
children_inspect(compact),
|
93
|
+
if @meta.size>0 then
|
94
|
+
', '+@meta.inspect
|
95
|
+
else '' end
|
96
|
+
]
|
97
|
+
end
|
98
|
+
|
99
|
+
def children_inspect(compact=true)
|
100
|
+
s = @children.inspect_more(compact,', ')
|
101
|
+
if @children.empty?
|
102
|
+
"[]"
|
103
|
+
elsif s.size < 70
|
104
|
+
s
|
105
|
+
else
|
106
|
+
"[\n"+
|
107
|
+
add_tabs(@children.inspect_more(compact,",\n ",false))+
|
108
|
+
"\n]"
|
109
|
+
end
|
70
110
|
end
|
71
111
|
|
72
112
|
end
|
73
113
|
|
114
|
+
class String
|
115
|
+
alias inspect_more inspect
|
116
|
+
end
|
117
|
+
|
118
|
+
class Array
|
119
|
+
def inspect_more(compact, join_string, add_brackets=true)
|
120
|
+
s = map {|x|
|
121
|
+
x.kind_of?(String) ? x.inspect :
|
122
|
+
x.kind_of?(MDElement) ? x.inspect(compact) :
|
123
|
+
(raise "WTF #{x.class} #{x.inspect}")
|
124
|
+
}.join(join_string)
|
125
|
+
|
126
|
+
add_brackets ? "[#{s}]" : s
|
127
|
+
end
|
128
|
+
end
|
74
129
|
# The Maruku class represent the whole document
|
75
130
|
# and holds global data.
|
76
131
|
|
@@ -78,32 +133,4 @@ class Maruku < MDElement
|
|
78
133
|
attr_accessor :refs
|
79
134
|
attr_accessor :footnotes
|
80
135
|
attr_accessor :abbreviations
|
81
|
-
# an instance of Section (see below)
|
82
|
-
attr_accessor :toc
|
83
|
-
end
|
84
|
-
|
85
|
-
class MDElement
|
86
|
-
|
87
|
-
# This represents a section in the TOC.
|
88
|
-
class Section
|
89
|
-
# a Fixnum, is == header_element.meta[:level]
|
90
|
-
attr_accessor :section_level
|
91
|
-
|
92
|
-
# An array of fixnum, like [1,2,5] for Section 1.2.5
|
93
|
-
attr_accessor :section_number
|
94
|
-
|
95
|
-
# reference to header (header has h.meta[:section] to self)
|
96
|
-
attr_accessor :header_element
|
97
|
-
|
98
|
-
# Array of immediate children of this element
|
99
|
-
attr_accessor :immediate_children
|
100
|
-
# Array of Section inside this section
|
101
|
-
attr_accessor :section_children
|
102
|
-
|
103
|
-
|
104
|
-
def initialize
|
105
|
-
@immediate_children = []
|
106
|
-
@section_children = []
|
107
|
-
end
|
108
|
-
end
|
109
136
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
class MDElement
|
5
|
+
|
6
|
+
# yields to each element of specified node_type
|
7
|
+
def each_element(e_node_type, &block)
|
8
|
+
@children.each do |c|
|
9
|
+
if c.kind_of? MDElement
|
10
|
+
if (not e_node_type) || (e_node_type == c.node_type)
|
11
|
+
block.call c
|
12
|
+
end
|
13
|
+
c.each_element(e_node_type, &block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Apply passed block to each String in the hierarchy.
|
19
|
+
def replace_each_string(&block)
|
20
|
+
for c in @children
|
21
|
+
if c.kind_of? MDElement
|
22
|
+
c.replace_each_string(&block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
processed = []
|
27
|
+
until @children.empty?
|
28
|
+
c = @children.shift
|
29
|
+
if c.kind_of? String
|
30
|
+
result = block.call(c)
|
31
|
+
[*result].each do |e| processed << e end
|
32
|
+
else
|
33
|
+
processed << c
|
34
|
+
end
|
35
|
+
end
|
36
|
+
@children = processed
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -1,18 +1,26 @@
|
|
1
1
|
require 'maruku'
|
2
2
|
require 'bluecloth'
|
3
3
|
|
4
|
+
|
4
5
|
data = $stdin.read
|
5
6
|
|
6
7
|
num = 10
|
7
8
|
|
8
|
-
|
9
|
+
methods =
|
9
10
|
[
|
10
11
|
|
11
12
|
[BlueCloth, :to_html],
|
12
|
-
[Maruku, :
|
13
|
-
[Maruku, :
|
13
|
+
[Maruku, :class],
|
14
|
+
# [Maruku, :to_html],
|
15
|
+
# [Maruku, :to_latex]
|
14
16
|
|
15
|
-
]
|
17
|
+
]*2
|
18
|
+
|
19
|
+
#methods = [[Maruku, :class]]
|
20
|
+
#num = 10
|
21
|
+
|
22
|
+
stats =
|
23
|
+
methods .map do |c, method|
|
16
24
|
puts "Computing for #{c}"
|
17
25
|
|
18
26
|
start = Time.now
|
@@ -0,0 +1,318 @@
|
|
1
|
+
require 'maruku'
|
2
|
+
require 'maruku/helpers'
|
3
|
+
|
4
|
+
require 'maruku/parse_span_better'
|
5
|
+
|
6
|
+
class Maruku
|
7
|
+
|
8
|
+
|
9
|
+
class TestNewParser
|
10
|
+
include Helpers
|
11
|
+
include MarukuErrors
|
12
|
+
|
13
|
+
# 5 accented letters in italian, encoded as UTF-8
|
14
|
+
AccIta8 = "\303\240\303\250\303\254\303\262\303\271"
|
15
|
+
|
16
|
+
# Same letters, written in ISO-8859-1 (one byte per letter)
|
17
|
+
AccIta1 = "\340\350\354\362\371"
|
18
|
+
|
19
|
+
# The word MA-RU-KU, written in katakana using UTF-8
|
20
|
+
Maruku8 = "\343\203\236\343\203\253\343\202\257"
|
21
|
+
|
22
|
+
def do_it(verbose, break_on_first_error)
|
23
|
+
good_cases = [
|
24
|
+
["", [], 'Empty string gives empty list'],
|
25
|
+
["a", ["a"], 'Easy char'],
|
26
|
+
[' ', [' '], 'One char => one string'],
|
27
|
+
[' ', [' '], 'Two chars => one char'],
|
28
|
+
['a b', ['a b'], 'Spaces are compressed'],
|
29
|
+
['a b', ['a b'], 'Newlines are spaces'],
|
30
|
+
["a\nb", ['a b'], 'Newlines are spaces'],
|
31
|
+
["a\n b", ['a b'], 'Compress newlines 1'],
|
32
|
+
["a \nb", ['a b'], 'Compress newlines 2'],
|
33
|
+
[" \nb", [' b'], 'Compress newlines 3'],
|
34
|
+
["\nb", [' b'], 'Compress newlines 4'],
|
35
|
+
["b\n", ['b '], 'Compress newlines 5'],
|
36
|
+
["\n", [' '], 'Compress newlines 6'],
|
37
|
+
["\n\n\n", [' '], 'Compress newlines 7'],
|
38
|
+
|
39
|
+
[nil, :throw, "Should throw on nil input"],
|
40
|
+
|
41
|
+
# Code blocks
|
42
|
+
["`" , :throw, 'Unclosed single ticks'],
|
43
|
+
["``" , :throw, 'Unclosed double ticks'],
|
44
|
+
["`a`" , [md_code('a')], 'Simple inline code'],
|
45
|
+
["`` ` ``" , [md_code('`')], ],
|
46
|
+
["`` \\` ``" , [md_code('\\`')], ],
|
47
|
+
["``a``" , [md_code('a')], ],
|
48
|
+
["`` a ``" , [md_code('a')], ],
|
49
|
+
|
50
|
+
# Newlines
|
51
|
+
["a \n", ['a',md_el(:linebreak)], 'Two spaces give br.'],
|
52
|
+
["a \n", ['a '], 'Newlines 2'],
|
53
|
+
[" \n", [md_el(:linebreak)], 'Newlines 3'],
|
54
|
+
[" \n \n", [md_el(:linebreak),md_el(:linebreak)],'Newlines 3'],
|
55
|
+
[" \na \n", [md_el(:linebreak),'a',md_el(:linebreak)],'Newlines 3'],
|
56
|
+
|
57
|
+
# Inline HTML
|
58
|
+
["a < b", ['a < b'], '< can be on itself'],
|
59
|
+
["<hr>", [md_html('<hr />')], 'HR will be sanitized'],
|
60
|
+
["<hr/>", [md_html('<hr />')], 'Closed tag is ok'],
|
61
|
+
["<hr />", [md_html('<hr />')], 'Closed tag is ok 2'],
|
62
|
+
["<hr/>a", [md_html('<hr />'),'a'], 'Closed tag is ok 2'],
|
63
|
+
["<em></em>a", [md_html('<em></em>'),'a'], 'Inline HTML 1'],
|
64
|
+
["<em>e</em>a", [md_html('<em>e</em>'),'a'], 'Inline HTML 2'],
|
65
|
+
["a<em>e</em>b", ['a',md_html('<em>e</em>'),'b'], 'Inline HTML 3'],
|
66
|
+
["<em>e</em>a<em>f</em>",
|
67
|
+
[md_html('<em>e</em>'),'a',md_html('<em>f</em>')],
|
68
|
+
'Inline HTML 4'],
|
69
|
+
["<em>e</em><em>f</em>a",
|
70
|
+
[md_html('<em>e</em>'),md_html('<em>f</em>'),'a'],
|
71
|
+
'Inline HTML 5'],
|
72
|
+
|
73
|
+
["<img src='a' />", [md_html("<img src='a' />")], 'Attributes'],
|
74
|
+
["<img src='a'/>"],
|
75
|
+
|
76
|
+
# emphasis
|
77
|
+
["**", :throw, 'Unclosed double **'],
|
78
|
+
["\\*", ['*'], 'Escaping of *'],
|
79
|
+
["a *b* ", ['a ', md_em('b'),' '], 'Emphasis 1'],
|
80
|
+
["a *b*", ['a ', md_em('b')], 'Emphasis 2'],
|
81
|
+
["a * b", ['a * b'], 'Emphasis 3'],
|
82
|
+
["a * b*", :throw, 'Unclosed emphasis'],
|
83
|
+
# same with underscore
|
84
|
+
["__", :throw, 'Unclosed double __'],
|
85
|
+
["\\_", ['_'], 'Escaping of _'],
|
86
|
+
["a _b_ ", ['a ', md_em('b'),' '], 'Emphasis 4'],
|
87
|
+
["a _b_", ['a ', md_em('b')], 'Emphasis 5'],
|
88
|
+
["a _ b", ['a _ b'], 'Emphasis 6'],
|
89
|
+
["a _ b_", :throw, 'Unclosed emphasis'],
|
90
|
+
["_b_", [md_em('b')], 'Emphasis 7'],
|
91
|
+
["_b_ _c_", [md_em('b'),' ',md_em('c')], 'Emphasis 8'],
|
92
|
+
["_b__c_", [md_em('b'),md_em('c')], 'Emphasis 9'],
|
93
|
+
# strong
|
94
|
+
["**a*", :throw, 'Unclosed double ** 2'],
|
95
|
+
["\\**a*", ['*', md_em('a')], 'Escaping of *'],
|
96
|
+
["a **b** ", ['a ', md_strong('b'),' '], 'Emphasis 1'],
|
97
|
+
["a **b**", ['a ', md_strong('b')], 'Emphasis 2'],
|
98
|
+
["a ** b", ['a ** b'], 'Emphasis 3'],
|
99
|
+
["a ** b**", :throw, 'Unclosed emphasis'],
|
100
|
+
["**b****c**", [md_strong('b'),md_strong('c')], 'Emphasis 9'],
|
101
|
+
# strong (with underscore)
|
102
|
+
["__a_", :throw, 'Unclosed double __ 2'],
|
103
|
+
["\\__a_", ['_', md_em('a')], 'Escaping of _'],
|
104
|
+
["a __b__ ", ['a ', md_strong('b'),' '], 'Emphasis 1'],
|
105
|
+
["a __b__", ['a ', md_strong('b')], 'Emphasis 2'],
|
106
|
+
["a __ b", ['a __ b'], 'Emphasis 3'],
|
107
|
+
["a __ b__", :throw, 'Unclosed emphasis'],
|
108
|
+
["__b____c__", [md_strong('b'),md_strong('c')], 'Emphasis 9'],
|
109
|
+
# extra strong
|
110
|
+
["***a**", :throw, 'Unclosed triple *** '],
|
111
|
+
["\\***a**", ['*', md_strong('a')], 'Escaping of *'],
|
112
|
+
["a ***b*** ", ['a ', md_emstrong('b'),' '], 'Strong elements'],
|
113
|
+
["a ***b***", ['a ', md_emstrong('b')]],
|
114
|
+
["a *** b", ['a *** b']],
|
115
|
+
["a ** * b", ['a ** * b']],
|
116
|
+
["***b******c***", [md_emstrong('b'),md_emstrong('c')]],
|
117
|
+
["a *** b***", :throw, 'Unclosed emphasis'],
|
118
|
+
# same with underscores
|
119
|
+
["___a__", :throw, 'Unclosed triple *** '],
|
120
|
+
["\\___a__", ['_', md_strong('a')], 'Escaping of *'],
|
121
|
+
["a ___b___ ", ['a ', md_emstrong('b'),' '], 'Strong elements'],
|
122
|
+
["a ___b___", ['a ', md_emstrong('b')]],
|
123
|
+
["a ___ b", ['a ___ b']],
|
124
|
+
["a __ _ b", ['a __ _ b']],
|
125
|
+
["___b______c___", [md_emstrong('b'),md_emstrong('c')]],
|
126
|
+
["a ___ b___", :throw, 'Unclosed emphasis'],
|
127
|
+
# mixing is bad
|
128
|
+
["*a_", :throw, 'Mixing is bad'],
|
129
|
+
["_a*", :throw],
|
130
|
+
["**a__", :throw],
|
131
|
+
["__a**", :throw],
|
132
|
+
["___a***", :throw],
|
133
|
+
["***a___", :throw],
|
134
|
+
# links of the form [text][ref]
|
135
|
+
["\\[a]", ["[a]"], 'Escaping 1'],
|
136
|
+
["\\[a\\]", ["[a]"], 'Escaping 2'],
|
137
|
+
["[a]", ["a"], 'Not a link'],
|
138
|
+
["[a][]", [ md_link(["a"],'')], 'Empty link'],
|
139
|
+
["[a][]b", [ md_link(["a"],''),'b'], 'Empty link'],
|
140
|
+
["[a\\]][]", [ md_link(["a]"],'')], 'Escape inside link'],
|
141
|
+
|
142
|
+
["[a", :throw, 'Link not closed'],
|
143
|
+
["[a][", :throw, 'Ref not closed'],
|
144
|
+
|
145
|
+
# links of the form [text](url)
|
146
|
+
["\\[a](b)", ["[a](b)"], 'Links'],
|
147
|
+
["[a](url)c", [md_im_link(['a'],'url'),'c'], 'url'],
|
148
|
+
["[a]( url )c" ],
|
149
|
+
["[a] ( url )c" ],
|
150
|
+
["[a] ( url)c" ],
|
151
|
+
|
152
|
+
["[a](ur:/l/ 'Title')", [md_im_link(['a'],'ur:/l/','Title')],
|
153
|
+
'url and title'],
|
154
|
+
["[a] ( ur:/l/ \"Title\")" ],
|
155
|
+
["[a] ( ur:/l/ \"Title\")" ],
|
156
|
+
["[a]( ur:/l/ Title)", :throw, "Must quote title" ],
|
157
|
+
|
158
|
+
["[a](url 'Tit\\\"l\\\\e')", [md_im_link(['a'],'url','Tit"l\\e')],
|
159
|
+
'url and title escaped'],
|
160
|
+
["[a] ( url \"Tit\\\"l\\\\e\")" ],
|
161
|
+
["[a] ( url \"Tit\\\"l\\\\e\" )" ],
|
162
|
+
['[a] ( url "Tit\\"l\\\\e" )' ],
|
163
|
+
["[a]()", [md_im_link(['a'],'')], 'No URL is OK'],
|
164
|
+
|
165
|
+
["[a](\"Title\")", :throw, "No url specified" ],
|
166
|
+
["[a](url \"Title)", :throw, "Unclosed quotes" ],
|
167
|
+
["[a](url \"Title\\\")", :throw],
|
168
|
+
["[a](url \"Title\" ", :throw],
|
169
|
+
|
170
|
+
["[a](url \'Title\")", :throw, "Mixing is bad" ],
|
171
|
+
["[a](url \"Title\')"],
|
172
|
+
|
173
|
+
["[a](/url)", [md_im_link(['a'],'/url')], 'Funny chars in url'],
|
174
|
+
["[a](#url)", [md_im_link(['a'],'#url')]],
|
175
|
+
["[a](</script?foo=1&bar=2>)", [md_im_link(['a'],'/script?foo=1&bar=2')]],
|
176
|
+
|
177
|
+
|
178
|
+
# Images
|
179
|
+
["\\", ['!', md_im_link(['a'],'url') ], 'Escaping images'],
|
180
|
+
|
181
|
+
["", [md_im_image(['a'],'url')], 'Image no title'],
|
182
|
+
["" ],
|
183
|
+
["![a] ( url )" ],
|
184
|
+
["![a] ( url)" ],
|
185
|
+
|
186
|
+
["", [md_im_image(['a'],'url','ti"tle')], 'Image with title'],
|
187
|
+
['' ],
|
188
|
+
|
189
|
+
["" ],
|
191
|
+
["![a] ('url )" ],
|
192
|
+
|
193
|
+
["![a][imref]", [md_image(['a'],'imref')], 'Image with ref'],
|
194
|
+
["![a][ imref]"],
|
195
|
+
["![a][ imref ]"],
|
196
|
+
["![a][\timref\t]"],
|
197
|
+
|
198
|
+
['<http://example.com/?foo=1&bar=2>',
|
199
|
+
[md_url('http://example.com/?foo=1&bar=2')], 'Immediate link'],
|
200
|
+
['a<http://example.com/?foo=1&bar=2>b',
|
201
|
+
['a',md_url('http://example.com/?foo=1&bar=2'),'b'] ],
|
202
|
+
['<andrea@censi.org>',
|
203
|
+
[md_email('andrea@censi.org')], 'Email address'],
|
204
|
+
['<mailto:andrea@censi.org>'],
|
205
|
+
|
206
|
+
["a<!-- -->b", ['a',md_html('<!-- -->'),'b'],
|
207
|
+
'HTML Comment'],
|
208
|
+
|
209
|
+
["a<!--", :throw, 'Bad HTML Comment'],
|
210
|
+
["a<!-- ", :throw, 'Bad HTML Comment'],
|
211
|
+
|
212
|
+
["a <b", :throw, 'Bad HTML 1'],
|
213
|
+
["<b", :throw, 'Bad HTML 2'],
|
214
|
+
["<b!", :throw, 'Bad HTML 3'],
|
215
|
+
['`<div>`, `<table>`, `<pre>`, `<p>`',
|
216
|
+
[md_code('<div>'),', ',md_code('<table>'),', ',
|
217
|
+
md_code('<pre>'),', ',md_code('<p>')],
|
218
|
+
'Multiple HTLM tags'],
|
219
|
+
|
220
|
+
["&andrea", ["&andrea"], 'Parsing of entities'],
|
221
|
+
# no escaping is allowed
|
222
|
+
# ["\\&andrea;", ["&andrea;"]],
|
223
|
+
["&&andrea;", ["&", md_entity('andrea')] ],
|
224
|
+
["&123;;&",[md_entity('123'),';',md_entity('amp')]],
|
225
|
+
|
226
|
+
["a\nThe [syntax page] [s] provides",
|
227
|
+
['a The ', md_link(['syntax page'],'s'), ' provides'], 'Regression'],
|
228
|
+
|
229
|
+
["#{Maruku8}", [Maruku8], "Reading UTF-8"],
|
230
|
+
["#{AccIta1}", [AccIta8], "Converting ISO-8859-1 to UTF-8",
|
231
|
+
{:encoding => 'iso-8859-1'}],
|
232
|
+
]
|
233
|
+
|
234
|
+
count = 1; last_comment=""; last_expected=:throw
|
235
|
+
good_cases.each do |t|
|
236
|
+
if not t[1]
|
237
|
+
t[1] = last_expected
|
238
|
+
else
|
239
|
+
last_expected = t[1]
|
240
|
+
end
|
241
|
+
if not t[2]
|
242
|
+
t[2] = last_comment + " #{count+=1}"
|
243
|
+
else
|
244
|
+
last_comment = t[2]; count=1
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
|
249
|
+
@verbose = verbose
|
250
|
+
m = Maruku.new
|
251
|
+
m.meta[:on_error] = :raise
|
252
|
+
|
253
|
+
good_cases.each do |input, expected, comment|
|
254
|
+
output = nil
|
255
|
+
begin
|
256
|
+
output = m.parse_span_better(input)
|
257
|
+
#lines = Maruku.split_lines input
|
258
|
+
#output = m.parse_lines_as_span(lines)
|
259
|
+
rescue Exception => e
|
260
|
+
if not expected == :throw
|
261
|
+
ex = e.inspect+ "\n"+ e.backtrace.join("\n")
|
262
|
+
s = comment+describe_difference(input, expected, output)
|
263
|
+
|
264
|
+
print_status(comment,'CRASHED :-(', ex+s)
|
265
|
+
raise e if @break_on_first_error
|
266
|
+
else
|
267
|
+
print_status(comment,'OK')
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
if not expected == :throw
|
272
|
+
if not (expected == output)
|
273
|
+
s = comment+describe_difference(input, expected, output)
|
274
|
+
print_status(comment, 'FAILED', s)
|
275
|
+
break if break_on_first_error
|
276
|
+
else
|
277
|
+
print_status(comment, 'OK')
|
278
|
+
end
|
279
|
+
else # I expected a raise
|
280
|
+
if output
|
281
|
+
s = comment+describe_difference(input, expected, output)
|
282
|
+
|
283
|
+
print_status(comment, 'FAILED (no throw)', s)
|
284
|
+
break if break_on_first_error
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
PAD=40
|
292
|
+
def print_status(comment, status, verbose_text=nil)
|
293
|
+
if comment.size < PAD
|
294
|
+
comment = comment + (" "*(PAD-comment.size))
|
295
|
+
end
|
296
|
+
puts "- #{comment} #{status}"
|
297
|
+
if @verbose and verbose_text
|
298
|
+
puts verbose_text
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
|
303
|
+
def describe_difference(input, expected, output)
|
304
|
+
"\nInput:\n #{input.inspect}" +
|
305
|
+
"\nExpected:\n #{expected.inspect}" +
|
306
|
+
"\nOutput:\n #{output.inspect}\n"+
|
307
|
+
"\nExpected(more):\n #{expected.inspect}" +
|
308
|
+
"\nOutput(more):\n #{output.inspect}"
|
309
|
+
end
|
310
|
+
|
311
|
+
end # class Test
|
312
|
+
end
|
313
|
+
|
314
|
+
verbose = ARGV.include? 'v'
|
315
|
+
break_on_first = ARGV.include? 'b'
|
316
|
+
Maruku::TestNewParser.new.do_it(verbose, break_on_first)
|
317
|
+
|
318
|
+
|