maruku 0.2.13 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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.rb
CHANGED
@@ -18,10 +18,15 @@
|
|
18
18
|
|
19
19
|
# Structures definition
|
20
20
|
require 'maruku/structures'
|
21
|
+
# Less typing
|
22
|
+
require 'maruku/helpers'
|
21
23
|
|
22
24
|
# Code for parsing whole Markdown documents
|
23
25
|
require 'maruku/parse_doc'
|
24
26
|
|
27
|
+
# Ugly things kept in a closet
|
28
|
+
require 'maruku/string_utils'
|
29
|
+
|
25
30
|
# A class for reading and sanitizing inline HTML
|
26
31
|
require 'maruku/html_helper'
|
27
32
|
|
@@ -29,10 +34,12 @@ require 'maruku/html_helper'
|
|
29
34
|
require 'maruku/parse_block'
|
30
35
|
|
31
36
|
# Code for parsing Markdown span-level elements
|
32
|
-
require 'maruku/
|
37
|
+
require 'maruku/parse_span_better'
|
38
|
+
|
39
|
+
require 'maruku/structures_iterators'
|
40
|
+
|
41
|
+
require 'maruku/errors_management'
|
33
42
|
|
34
|
-
# Ugly things kept in a closet
|
35
|
-
require 'maruku/string_utils'
|
36
43
|
|
37
44
|
# Code for creating a table of contents
|
38
45
|
require 'maruku/toc'
|
@@ -49,5 +56,8 @@ require 'maruku/to_latex'
|
|
49
56
|
require 'maruku/to_latex_strings'
|
50
57
|
require 'maruku/to_latex_entities'
|
51
58
|
|
59
|
+
# Pretty print
|
60
|
+
require 'maruku/to_markdown'
|
61
|
+
|
52
62
|
# Exporting to text: strips all formatting (not complete)
|
53
63
|
require 'maruku/to_s'
|
@@ -0,0 +1,75 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
# Any method that detects formatting error calls the
|
4
|
+
# error() method.
|
5
|
+
# if @meta[:on_error] ==
|
6
|
+
#
|
7
|
+
# - :warning write on the standard err (or @error_stream if defined),
|
8
|
+
# then do your best.
|
9
|
+
# - :ignore be shy and try to continue
|
10
|
+
# - :raise raises a MarukuException
|
11
|
+
#
|
12
|
+
# default is :raise
|
13
|
+
|
14
|
+
class MarukuException < RuntimeError
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
module MarukuErrors
|
20
|
+
Default_on_error = :warning
|
21
|
+
|
22
|
+
def maruku_error(s,src=nil,con=nil)
|
23
|
+
policy = @doc ? (@doc.meta[:on_error] || Default_on_error) : :raise
|
24
|
+
|
25
|
+
case policy
|
26
|
+
when :ignore
|
27
|
+
when :raise
|
28
|
+
raise_error describe_error(s,src,con)
|
29
|
+
when :warning
|
30
|
+
tell_user describe_error(s,src,con)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
alias error maruku_error
|
35
|
+
|
36
|
+
def raise_error(s)
|
37
|
+
raise MarukuException, s, caller
|
38
|
+
end
|
39
|
+
|
40
|
+
def tell_user(s)
|
41
|
+
n = 75
|
42
|
+
(@error_stream || $stderr) <<
|
43
|
+
" "+"_"*n << "\n"<<
|
44
|
+
"| Maruku tells you (#{caller[0]})\n" <<
|
45
|
+
"+"+"-"*n +"\n"+
|
46
|
+
add_tabs(s,1,'| ') << "\n" <<
|
47
|
+
"+" << "-"*n << "\n" <<
|
48
|
+
add_tabs(caller.join("\n"),1,'!') << "\n" <<
|
49
|
+
"\\" << "_"*n << "\n"
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_error_stream(os)
|
53
|
+
@error_stream = os
|
54
|
+
end
|
55
|
+
|
56
|
+
def describe_error(s,src,con)
|
57
|
+
t = s
|
58
|
+
if src
|
59
|
+
t += "\n#{src.describe}\n"
|
60
|
+
end
|
61
|
+
if con
|
62
|
+
t += "\n#{con.describe}\n"
|
63
|
+
end
|
64
|
+
t
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
class MDElement
|
70
|
+
include MarukuErrors
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
|
@@ -0,0 +1,164 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
# A series of helper functions for creating elements
|
4
|
+
|
5
|
+
module Helpers
|
6
|
+
|
7
|
+
def md_el(node_type, children=[], meta={})
|
8
|
+
e=MDElement.new(node_type, children, meta)
|
9
|
+
e.doc = self
|
10
|
+
e
|
11
|
+
end
|
12
|
+
|
13
|
+
def md_code(code)
|
14
|
+
md_el(:inline_code, [], {:raw_code => code})
|
15
|
+
end
|
16
|
+
|
17
|
+
def md_par(children, meta={})
|
18
|
+
md_el(:paragraph, [], meta)
|
19
|
+
end
|
20
|
+
|
21
|
+
def md_html(raw_html)
|
22
|
+
e = md_el(:raw_html, [], {:raw_html=>raw_html})
|
23
|
+
begin
|
24
|
+
# remove newlines and whitespace at begin
|
25
|
+
# end end of string, or else REXML gets confused
|
26
|
+
raw_html = raw_html.gsub(/\A\s*</,'<').
|
27
|
+
gsub(/>[\s\n]*\Z/,'>')
|
28
|
+
e.instance_variable_set :@parsed_html,
|
29
|
+
REXML::Document.new(raw_html)
|
30
|
+
|
31
|
+
rescue Exception => ex
|
32
|
+
tell_user "Malformed block of HTML:\n"+
|
33
|
+
add_tabs(raw_html,1,'|')
|
34
|
+
# " #{raw_html.inspect}\n\n"+ex.inspect
|
35
|
+
end
|
36
|
+
e
|
37
|
+
end
|
38
|
+
|
39
|
+
def md_link(children, ref_id)
|
40
|
+
md_el(:link, children, {:ref_id=>ref_id.downcase})
|
41
|
+
end
|
42
|
+
|
43
|
+
def md_im_link(children, url, title=nil)
|
44
|
+
md_el(:link, children, {:url=>url,:title=>title})
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def md_image(children, ref_id)
|
49
|
+
md_el(:image, children, {:ref_id=>ref_id})
|
50
|
+
end
|
51
|
+
|
52
|
+
def md_im_image(children, url, title=nil)
|
53
|
+
md_el(:image, children, {:url=>url,:title=>title})
|
54
|
+
end
|
55
|
+
|
56
|
+
def md_em(children)
|
57
|
+
md_el(:emphasis, [children].flatten)
|
58
|
+
end
|
59
|
+
|
60
|
+
def md_strong(children)
|
61
|
+
md_el(:strong, [children].flatten)
|
62
|
+
end
|
63
|
+
|
64
|
+
def md_emstrong(children)
|
65
|
+
md_strong(md_em(children))
|
66
|
+
end
|
67
|
+
|
68
|
+
# <http://www.example.com/>
|
69
|
+
def md_url(url)
|
70
|
+
md_el(:immediate_link, [], {:url=>url})
|
71
|
+
end
|
72
|
+
|
73
|
+
# <andrea@rubyforge.org>
|
74
|
+
# <mailto:andrea@rubyforge.org>
|
75
|
+
def md_email(email)
|
76
|
+
md_el(:email_address, [], {:email=>email})
|
77
|
+
end
|
78
|
+
|
79
|
+
def md_entity(entity_name)
|
80
|
+
md_el(:entity, [], {:entity_name=>entity_name})
|
81
|
+
end
|
82
|
+
|
83
|
+
# Markdown extra
|
84
|
+
def md_foot_ref(ref_id)
|
85
|
+
md_el(:footnote_reference, [], {:footnote_id=>ref_id})
|
86
|
+
end
|
87
|
+
|
88
|
+
def md_par(children, meta={})
|
89
|
+
md_el(:paragraph, children, meta)
|
90
|
+
end
|
91
|
+
|
92
|
+
# [1]: http://url [properties]
|
93
|
+
def md_ref_def(ref_id, url, title=nil, meta={})
|
94
|
+
meta[:url] = url
|
95
|
+
meta[:ref_id] = ref_id
|
96
|
+
meta[:title] = title if title
|
97
|
+
md_el(:ref_definition, [], meta)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class MDElement
|
102
|
+
# outputs abbreviated form
|
103
|
+
def inspect2
|
104
|
+
case @node_type
|
105
|
+
when :paragraph
|
106
|
+
"md_par(%s)" % children_inspect
|
107
|
+
when :footnote_reference
|
108
|
+
"md_foot_ref(%s)" % @meta[:footnote_id].inspect
|
109
|
+
when :entity
|
110
|
+
"md_entity(%s)" % @meta[:entity_name].inspect
|
111
|
+
when :email_address
|
112
|
+
"md_email(%s)" % @meta[:email].inspect
|
113
|
+
when :inline_code
|
114
|
+
"md_code(%s)" % @meta[:raw_code].inspect
|
115
|
+
when :raw_html
|
116
|
+
"md_html(%s)" % @meta[:raw_html].inspect
|
117
|
+
when :emphasis
|
118
|
+
"md_em(%s)" % children_inspect
|
119
|
+
when :strong
|
120
|
+
"md_strong(%s)" % children_inspect
|
121
|
+
when :immediate_link
|
122
|
+
"md_url(%s)" % @meta[:url].inspect
|
123
|
+
when :image
|
124
|
+
if @meta[:ref_id]
|
125
|
+
"md_image(%s,%s)" % [
|
126
|
+
children_inspect, @meta[:ref_id].inspect]
|
127
|
+
else
|
128
|
+
"md_im_image(%s, %s %s)" % [
|
129
|
+
children_inspect, @meta[:url].inspect,
|
130
|
+
(title=@meta[:title]) ? (", "+ title.inspect) : ""
|
131
|
+
]
|
132
|
+
end
|
133
|
+
when :link
|
134
|
+
if @meta[:ref_id]
|
135
|
+
"md_link(%s,%s)" % [
|
136
|
+
children_inspect, @meta[:ref_id].inspect]
|
137
|
+
else
|
138
|
+
"md_im_link(%s, %s %s)" % [
|
139
|
+
children_inspect, @meta[:url].inspect,
|
140
|
+
(title=@meta[:title]) ? (", "+ title.inspect) : ""
|
141
|
+
]
|
142
|
+
end
|
143
|
+
when :ref_definition
|
144
|
+
"md_ref_def(%s, %s %s)" %
|
145
|
+
[
|
146
|
+
@meta[:ref_id].inspect,
|
147
|
+
@meta[:url].inspect,
|
148
|
+
@meta[:title] ? ","+@meta[:title].inspect : ""
|
149
|
+
]
|
150
|
+
else
|
151
|
+
nil
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
|
159
|
+
|
160
|
+
|
161
|
+
|
162
|
+
|
163
|
+
|
164
|
+
|
data/lib/maruku/html_helper.rb
CHANGED
@@ -1,16 +1,21 @@
|
|
1
1
|
|
2
2
|
class Maruku
|
3
3
|
|
4
|
-
#
|
4
|
+
# This class helps me read and sanitize HTML blocks
|
5
|
+
|
6
|
+
# I tried to do this with REXML, but wasn't able to. (suggestions?)
|
5
7
|
|
6
8
|
class HTMLHelper
|
7
|
-
|
9
|
+
include MarukuStrings
|
10
|
+
|
11
|
+
Tag = %r{^<(/)?(\w+)\s*([^>]*)>}m
|
8
12
|
EverythingElse = %r{^[^<]+}m
|
9
13
|
CommentStart = %r{^<!--}x
|
10
14
|
CommentEnd = %r{^.*-->}
|
11
15
|
TO_SANITIZE = ['img','hr']
|
12
16
|
|
13
|
-
attr_accessor :inside_comment
|
17
|
+
# attr_accessor :inside_comment
|
18
|
+
attr_reader :rest
|
14
19
|
|
15
20
|
def initialize
|
16
21
|
@rest = ""
|
@@ -21,8 +26,8 @@ class Maruku
|
|
21
26
|
end
|
22
27
|
|
23
28
|
def eat_this(line)
|
24
|
-
@rest = line
|
25
|
-
|
29
|
+
@rest = line + @rest
|
30
|
+
things_read = 0
|
26
31
|
until @rest.empty?
|
27
32
|
if @inside_comment
|
28
33
|
if @m = CommentEnd.match(@rest)
|
@@ -35,10 +40,12 @@ class Maruku
|
|
35
40
|
end
|
36
41
|
else
|
37
42
|
if @m = CommentStart.match(@rest)
|
43
|
+
things_read += 1
|
38
44
|
@inside_comment = true
|
39
45
|
@already += @m.pre_match + @m.to_s
|
40
46
|
@rest = @m.post_match
|
41
47
|
elsif @m = Tag.match(@rest)
|
48
|
+
things_read += 1
|
42
49
|
@already += @m.pre_match
|
43
50
|
@rest = @m.post_match
|
44
51
|
|
@@ -53,7 +60,13 @@ class Maruku
|
|
53
60
|
end
|
54
61
|
|
55
62
|
if TO_SANITIZE.include? tag
|
56
|
-
|
63
|
+
attributes.strip!
|
64
|
+
# puts "Attributes: #{attributes.inspect}"
|
65
|
+
if attributes.size > 0
|
66
|
+
@already += '<%s %s />' % [tag, attributes]
|
67
|
+
else
|
68
|
+
@already += '<%s />' % [tag]
|
69
|
+
end
|
57
70
|
elsif is_closing
|
58
71
|
@already += @m.to_s
|
59
72
|
if @tag_stack.last != tag
|
@@ -73,29 +86,36 @@ class Maruku
|
|
73
86
|
@already += @m.pre_match + @m.to_s
|
74
87
|
@rest = @m.post_match
|
75
88
|
else
|
76
|
-
|
89
|
+
error "Malformed HTML: not complete: #{@rest.inspect}"
|
77
90
|
end
|
78
91
|
end # not inside comment
|
79
92
|
|
80
93
|
# puts inspect
|
81
94
|
# puts "Read: #{@tag_stack.inspect}"
|
95
|
+
break if is_finished? and things_read>0
|
82
96
|
end
|
83
97
|
end
|
84
98
|
|
85
99
|
|
86
100
|
def error(s)
|
87
|
-
raise "Error: #{s} "+ inspect
|
101
|
+
raise RuntimeError, "Error: #{s} "+ inspect, caller
|
88
102
|
end
|
89
103
|
|
90
|
-
def inspect; "HTML READER\n comment=#{inside_comment} "+
|
91
|
-
"match=#{@m.to_s.inspect}"+
|
92
|
-
"
|
93
|
-
"
|
94
|
-
"\n
|
104
|
+
def inspect; "HTML READER\n comment=#{@inside_comment} "+
|
105
|
+
"match=#{@m.to_s.inspect}\n"+
|
106
|
+
"Tag stack = #{@tag_stack.inspect} \n"+
|
107
|
+
"Before:\n"+
|
108
|
+
add_tabs(@already,1,'|')+"\n"+
|
109
|
+
"After:\n"+
|
110
|
+
add_tabs(@rest,1,'|')+"\n"
|
111
|
+
|
95
112
|
end
|
113
|
+
|
114
|
+
|
96
115
|
def stuff_you_read
|
97
116
|
@already
|
98
117
|
end
|
118
|
+
|
99
119
|
def is_finished?
|
100
120
|
not @inside_comment and @tag_stack.empty?
|
101
121
|
end
|
data/lib/maruku/parse_block.rb
CHANGED
@@ -17,9 +17,11 @@
|
|
17
17
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
18
18
|
|
19
19
|
class Maruku
|
20
|
+
include Helpers
|
21
|
+
|
20
22
|
# Splits the string and calls parse_lines_as_markdown
|
21
23
|
def parse_text_as_markdown(text)
|
22
|
-
lines = split_lines(text)
|
24
|
+
lines = Maruku.split_lines(text)
|
23
25
|
parse_lines_as_markdown(lines)
|
24
26
|
end
|
25
27
|
|
@@ -74,7 +76,7 @@ class Maruku
|
|
74
76
|
|
75
77
|
# these do not produce output
|
76
78
|
when :footnote_text; read_footnote_text
|
77
|
-
when :
|
79
|
+
when :ref_definition; output << read_ref_definition
|
78
80
|
when :abbreviation; read_abbreviation
|
79
81
|
when :metadata; just_read_metadata = read_metadata
|
80
82
|
|
@@ -82,7 +84,7 @@ class Maruku
|
|
82
84
|
else
|
83
85
|
node_type = cur_line_node_type
|
84
86
|
line = shift_line
|
85
|
-
|
87
|
+
tell_user "Ignoring line '#{line}' type = #{node_type}"
|
86
88
|
end
|
87
89
|
|
88
90
|
if current_metadata and output.last
|
@@ -122,10 +124,8 @@ class Maruku
|
|
122
124
|
output
|
123
125
|
end
|
124
126
|
|
125
|
-
def create_md_element(node_type, children=[])
|
126
|
-
e = MDElement.new
|
127
|
-
e.node_type = node_type
|
128
|
-
e.children = children
|
127
|
+
def create_md_element(node_type, children=[], meta = {})
|
128
|
+
e = MDElement.new(node_type, children, meta)
|
129
129
|
e.doc = self
|
130
130
|
e
|
131
131
|
end
|
@@ -134,7 +134,8 @@ class Maruku
|
|
134
134
|
def cur_line_node_type; line_node_type top.first end
|
135
135
|
def cur_line; top.empty? ? nil : top.first end
|
136
136
|
def next_line; top.empty? ? nil : top[1] end
|
137
|
-
def next_line_node_type
|
137
|
+
def next_line_node_type
|
138
|
+
(top.size >= 2) ? line_node_type(top[1]) : nil end
|
138
139
|
def shift_line; top.shift; end
|
139
140
|
|
140
141
|
# reads a header (with ----- or ========)
|
@@ -191,41 +192,33 @@ class Maruku
|
|
191
192
|
while cur_line and not h.is_finished?
|
192
193
|
l=shift_line
|
193
194
|
# puts "html -> #{l.inspect}"
|
194
|
-
h.eat_this l
|
195
|
+
h.eat_this "\n"+l
|
195
196
|
end
|
196
197
|
rescue Exception => e
|
197
|
-
|
198
|
+
tell_user e.inspect + e.backtrace.join("\n")
|
198
199
|
# puts h.inspect
|
199
200
|
end
|
200
201
|
|
201
202
|
raw_html = h.stuff_you_read
|
202
203
|
|
203
|
-
|
204
|
-
|
205
|
-
begin
|
206
|
-
# remove newlines and whitespace at begin
|
207
|
-
# end end of string, or else REXML gets confused
|
208
|
-
raw_html = raw_html.gsub(/\A\s*</,'<').
|
209
|
-
gsub(/>[\s\n]*\Z/,'>')
|
210
|
-
e.meta[:parsed_html] = Document.new(raw_html)
|
211
|
-
rescue
|
212
|
-
#$stderr.puts "Malformed block of HTML:\n#{raw_html}"
|
213
|
-
#puts h.inspect
|
214
|
-
end
|
215
|
-
|
216
|
-
e.meta[:raw_html] = raw_html
|
217
|
-
e
|
204
|
+
md_html(raw_html)
|
218
205
|
end
|
219
206
|
|
220
207
|
def read_paragraph
|
221
208
|
lines = []
|
222
|
-
while cur_line
|
209
|
+
while cur_line
|
210
|
+
break if [:quote,:header3,:empty,:raw_html,:ref_definition].include?(
|
211
|
+
cur_line_node_type)
|
212
|
+
break if cur_line.strip.size == 0
|
213
|
+
|
214
|
+
break if [:header1,:header2].include? next_line_node_type
|
215
|
+
|
223
216
|
lines << shift_line
|
224
217
|
end
|
225
218
|
# dbg_describe_ary(lines, 'PAR')
|
226
219
|
children = parse_lines_as_span(lines)
|
227
220
|
|
228
|
-
|
221
|
+
md_par(children)
|
229
222
|
end
|
230
223
|
|
231
224
|
|
@@ -291,56 +284,56 @@ class Maruku
|
|
291
284
|
# This is the only ugly function in the code base.
|
292
285
|
# It is used to read list items, descriptions, footnote text
|
293
286
|
def read_indented_content(indentation, break_list, item_type)
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
287
|
+
lines =[]
|
288
|
+
# collect all indented lines
|
289
|
+
saw_empty = false; saw_anything_after = false
|
290
|
+
while cur_line
|
291
|
+
if cur_line_node_type == :empty
|
292
|
+
saw_empty = true
|
293
|
+
lines << shift_line
|
294
|
+
next
|
295
|
+
end
|
296
|
+
|
297
|
+
# after a white line
|
298
|
+
if saw_empty
|
299
|
+
# we expect things to be properly aligned
|
300
|
+
if number_of_leading_spaces(cur_line) < indentation
|
308
301
|
# debug "breaking for spaces: #{cur_line}"
|
309
|
-
|
310
|
-
end
|
311
|
-
saw_anything_after = true
|
312
|
-
else
|
313
|
-
break if break_list.include? cur_line_node_type
|
314
|
-
# break if cur_line_node_type != :text
|
315
|
-
end
|
316
|
-
|
317
|
-
# debug "Accepted '#{cur_line}'"
|
318
|
-
|
319
|
-
stripped = strip_indent(shift_line, indentation)
|
320
|
-
lines << stripped
|
321
|
-
|
322
|
-
# You are only required to indent the first line of
|
323
|
-
# a child paragraph.
|
324
|
-
if line_node_type(stripped) == :text
|
325
|
-
while cur_line && (cur_line_node_type == :text)
|
326
|
-
lines << strip_indent(shift_line, indentation)
|
327
|
-
end
|
302
|
+
break
|
328
303
|
end
|
304
|
+
saw_anything_after = true
|
305
|
+
else
|
306
|
+
break if break_list.include? cur_line_node_type
|
307
|
+
# break if cur_line_node_type != :text
|
329
308
|
end
|
330
|
-
|
331
|
-
want_my_paragraph = saw_anything_after ||
|
332
|
-
(saw_empty && (cur_line && (cur_line_node_type == item_type)))
|
333
309
|
|
334
|
-
|
335
|
-
|
310
|
+
# debug "Accepted '#{cur_line}'"
|
311
|
+
|
312
|
+
stripped = strip_indent(shift_line, indentation)
|
313
|
+
lines << stripped
|
336
314
|
|
337
|
-
|
338
|
-
|
315
|
+
# You are only required to indent the first line of
|
316
|
+
# a child paragraph.
|
317
|
+
if line_node_type(stripped) == :text
|
318
|
+
while cur_line && (cur_line_node_type == :text)
|
319
|
+
lines << strip_indent(shift_line, indentation)
|
320
|
+
end
|
339
321
|
end
|
340
|
-
|
341
|
-
return lines, want_my_paragraph
|
342
322
|
end
|
343
323
|
|
324
|
+
want_my_paragraph = saw_anything_after ||
|
325
|
+
(saw_empty && (cur_line && (cur_line_node_type == item_type)))
|
326
|
+
|
327
|
+
# dbg_describe_ary(lines, 'LI')
|
328
|
+
# create a new context
|
329
|
+
|
330
|
+
while lines.last && (line_node_type(lines.last) == :empty)
|
331
|
+
lines.pop
|
332
|
+
end
|
333
|
+
|
334
|
+
return lines, want_my_paragraph
|
335
|
+
end
|
336
|
+
|
344
337
|
|
345
338
|
def read_quote
|
346
339
|
lines = []
|
@@ -413,40 +406,42 @@ class Maruku
|
|
413
406
|
|
414
407
|
|
415
408
|
|
416
|
-
def
|
409
|
+
def read_ref_definition
|
417
410
|
line = shift_line
|
418
411
|
|
419
412
|
# if link is incomplete, shift next line
|
420
|
-
|
413
|
+
if cur_line && (cur_line_node_type != :ref_definition) &&
|
421
414
|
([1,2,3].include? number_of_leading_spaces(cur_line) )
|
422
415
|
line += " "+ shift_line
|
423
416
|
end
|
424
417
|
|
425
418
|
# puts "total= #{line}"
|
426
419
|
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
420
|
+
match = LinkRegex.match(line)
|
421
|
+
if not match
|
422
|
+
error "Link does not respect format: '#{line}'"
|
423
|
+
end
|
424
|
+
|
425
|
+
id = match[1]; url = match[2]; title = match[3];
|
426
|
+
id = id.strip.downcase
|
427
|
+
|
428
|
+
hash = self.refs[id] = {:url=>url,:title=>title}
|
429
|
+
|
430
|
+
stuff=match[4]
|
431
|
+
|
432
|
+
if stuff
|
433
|
+
stuff.split.each do |couple|
|
437
434
|
# puts "found #{couple}"
|
438
|
-
|
439
|
-
|
440
|
-
|
435
|
+
k, v = couple.split('=')
|
436
|
+
v ||= ""
|
437
|
+
if v[0,1]=='"' then v = v[1, v.size-2] end
|
441
438
|
# puts "key:_#{k}_ value=_#{v}_"
|
442
|
-
|
443
|
-
end
|
439
|
+
hash[k.to_sym] = v
|
444
440
|
end
|
445
|
-
# puts hash.inspect
|
446
|
-
|
447
|
-
else
|
448
|
-
raise "Link does not respect format: '#{line}'"
|
449
441
|
end
|
442
|
+
# puts hash.inspect
|
443
|
+
|
444
|
+
md_ref_def(id, url, meta={:title=>title})
|
450
445
|
end
|
451
446
|
|
452
447
|
def read_table
|
@@ -466,7 +461,8 @@ class Maruku
|
|
466
461
|
num_columns = align.size
|
467
462
|
|
468
463
|
if head.size != num_columns
|
469
|
-
|
464
|
+
error "Head does not have #{num_columns} columns: \n#{head.inspect}"
|
465
|
+
# XXX try to recover
|
470
466
|
return create_md_element(:linebreak)
|
471
467
|
end
|
472
468
|
|
@@ -476,7 +472,8 @@ class Maruku
|
|
476
472
|
row = split_cells(shift_line).map{|s|
|
477
473
|
create_md_element(:cell, parse_lines_as_span([s]))}
|
478
474
|
if head.size != num_columns
|
479
|
-
|
475
|
+
error "Row does not have #{num_columns} columns: \n#{row.inspect}"
|
476
|
+
# XXX try to recover
|
480
477
|
return create_md_element(:linebreak)
|
481
478
|
end
|
482
479
|
rows << row
|