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.
Files changed (86) hide show
  1. data/bin/maruku +23 -15
  2. data/bin/maruku0.3 +37 -0
  3. data/bin/marutest +277 -0
  4. data/docs/changelog-0.3.html +99 -0
  5. data/docs/changelog-0.3.md +84 -0
  6. data/docs/faq.html +46 -0
  7. data/docs/faq.md +32 -0
  8. data/docs/index.html +629 -64
  9. data/docs/markdown_extra2.html +67 -14
  10. data/docs/markdown_syntax.html +631 -94
  11. data/docs/markdown_syntax_2.html +152 -0
  12. data/docs/maruku.html +629 -64
  13. data/docs/maruku.md +108 -105
  14. data/docs/proposal.html +362 -55
  15. data/docs/proposal.md +133 -169
  16. data/docs/todo.html +30 -0
  17. data/lib/maruku.rb +13 -3
  18. data/lib/maruku/errors_management.rb +75 -0
  19. data/lib/maruku/helpers.rb +164 -0
  20. data/lib/maruku/html_helper.rb +33 -13
  21. data/lib/maruku/parse_block.rb +89 -92
  22. data/lib/maruku/parse_doc.rb +43 -18
  23. data/lib/maruku/parse_span.rb +17 -46
  24. data/lib/maruku/parse_span_better.rb +681 -0
  25. data/lib/maruku/string_utils.rb +17 -10
  26. data/lib/maruku/structures.rb +62 -35
  27. data/lib/maruku/structures_iterators.rb +39 -0
  28. data/lib/maruku/tests/benchmark.rb +12 -4
  29. data/lib/maruku/tests/new_parser.rb +318 -0
  30. data/lib/maruku/to_html.rb +113 -44
  31. data/lib/maruku/to_latex.rb +32 -14
  32. data/lib/maruku/to_markdown.rb +110 -0
  33. data/lib/maruku/toc.rb +35 -1
  34. data/lib/maruku/version.rb +10 -1
  35. data/lib/test.rb +29 -0
  36. data/tests/others/escaping.md +6 -4
  37. data/tests/others/links.md +1 -1
  38. data/tests/others/lists_after_paragraph.md +44 -0
  39. data/tests/unittest/abbreviations.md +71 -0
  40. data/tests/unittest/blank.md +43 -0
  41. data/tests/unittest/blanks_in_code.md +131 -0
  42. data/tests/unittest/code.md +64 -0
  43. data/tests/unittest/code2.md +59 -0
  44. data/tests/unittest/code3.md +121 -0
  45. data/tests/unittest/easy.md +36 -0
  46. data/tests/unittest/email.md +39 -0
  47. data/tests/unittest/encoding/iso-8859-1.md +9 -0
  48. data/tests/unittest/encoding/utf-8.md +38 -0
  49. data/tests/unittest/entities.md +174 -0
  50. data/tests/unittest/escaping.md +97 -0
  51. data/tests/unittest/extra_dl.md +81 -0
  52. data/tests/unittest/extra_header_id.md +96 -0
  53. data/tests/unittest/extra_table1.md +78 -0
  54. data/tests/unittest/footnotes.md +120 -0
  55. data/tests/unittest/headers.md +64 -0
  56. data/tests/unittest/hrule.md +77 -0
  57. data/tests/unittest/images.md +114 -0
  58. data/tests/unittest/inline_html.md +185 -0
  59. data/tests/unittest/links.md +162 -0
  60. data/tests/unittest/list1.md +80 -0
  61. data/tests/unittest/list2.md +75 -0
  62. data/tests/unittest/list3.md +111 -0
  63. data/tests/unittest/list4.md +43 -0
  64. data/tests/unittest/lists.md +262 -0
  65. data/tests/unittest/lists_after_paragraph.md +280 -0
  66. data/tests/unittest/lists_ol.md +323 -0
  67. data/tests/unittest/misc_sw.md +751 -0
  68. data/tests/unittest/notyet/escape.md +46 -0
  69. data/tests/unittest/notyet/header_after_par.md +85 -0
  70. data/tests/unittest/notyet/ticks.md +67 -0
  71. data/tests/unittest/notyet/triggering.md +210 -0
  72. data/tests/unittest/one.md +33 -0
  73. data/tests/unittest/paragraph.md +34 -0
  74. data/tests/unittest/paragraph_rules/dont_merge_ref.md +60 -0
  75. data/tests/unittest/paragraph_rules/tab_is_blank.md +43 -0
  76. data/tests/unittest/paragraphs.md +84 -0
  77. data/tests/unittest/recover/recover_links.md +32 -0
  78. data/tests/unittest/references/long_example.md +87 -0
  79. data/tests/unittest/references/spaces_and_numbers.md +27 -0
  80. data/tests/unittest/syntax_hl.md +99 -0
  81. data/tests/unittest/test.md +36 -0
  82. data/tests/unittest/wrapping.md +88 -0
  83. data/tests/utf8-files/simple.md +1 -0
  84. metadata +139 -86
  85. data/lib/maruku/maruku.rb +0 -50
  86. data/tests/a.md +0 -10
@@ -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 split_lines(s)
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
- $stderr.puts "Error: #{s} is not a list"
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
- $stderr.puts "#{prefix} (#{i+=1})##{l}#"
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 :ref if l =~ LinkRegex or l=~ IncompleteLink
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
- ^[ ]*\[(.+)\]: # id = $1
254
+ ^[ ]*\[([^\]]+)\]: # id = $1
248
255
  [ ]*
249
256
  <?(\S+)>? # url = $2
250
257
  [ ]*
@@ -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
- attr_accessor :meta
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
- @children = [];
68
- @node_type = :unset
69
- @meta = {};
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
- stats =
9
+ methods =
9
10
  [
10
11
 
11
12
  [BlueCloth, :to_html],
12
- [Maruku, :to_html],
13
- [Maruku, :to_latex]
13
+ [Maruku, :class],
14
+ # [Maruku, :to_html],
15
+ # [Maruku, :to_latex]
14
16
 
15
- ].map do |c, method|
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
+ ["\\![a](url)", ['!', md_im_link(['a'],'url') ], 'Escaping images'],
180
+
181
+ ["![a](url)", [md_im_image(['a'],'url')], 'Image no title'],
182
+ ["![a]( url )" ],
183
+ ["![a] ( url )" ],
184
+ ["![a] ( url)" ],
185
+
186
+ ["![a](url 'ti\"tle')", [md_im_image(['a'],'url','ti"tle')], 'Image with title'],
187
+ ['![a]( url "ti\\"tle")' ],
188
+
189
+ ["![a](url", :throw, 'Invalid images'],
190
+ ["![a( url )" ],
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;;&amp;",[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
+