marker 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +674 -0
- data/README +98 -0
- data/bin/marker +59 -0
- data/lib/marker/common.rb +40 -0
- data/lib/marker/headings.rb +79 -0
- data/lib/marker/language.treetop +679 -0
- data/lib/marker/links.rb +153 -0
- data/lib/marker/lists.rb +188 -0
- data/lib/marker/markup.rb +81 -0
- data/lib/marker/templates.rb +105 -0
- data/lib/marker/text.rb +96 -0
- data/lib/marker/verbatim.rb +48 -0
- data/lib/marker.rb +80 -0
- metadata +77 -0
data/lib/marker/links.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2009 Ryan Blue.
|
3
|
+
# Distributed under the terms of the GNU General Public License (GPL).
|
4
|
+
# See the LICENSE file for further information on the GPL.
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'marker/common'
|
8
|
+
|
9
|
+
module Marker #:nodoc:
|
10
|
+
class InternalLink < ParseNode
|
11
|
+
def to_html( options = {} )
|
12
|
+
"<a href='#{path(options)}'>#{label(:html, options)}</a>"
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s( options = {} )
|
16
|
+
f = options[:footnotes]
|
17
|
+
if f
|
18
|
+
l = label(:text, options)
|
19
|
+
n = f.add( path(options), l )
|
20
|
+
"#{l} [#{n}]"
|
21
|
+
else
|
22
|
+
"#{label(:text, options)} [#{path}]"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def path( options = {} )
|
27
|
+
p = options[:link_base] || ''
|
28
|
+
p.chomp! '/'
|
29
|
+
p += '/' + target
|
30
|
+
end
|
31
|
+
|
32
|
+
def label( format, options = {} )
|
33
|
+
if l
|
34
|
+
case format
|
35
|
+
when :html
|
36
|
+
l.to_html(options)
|
37
|
+
else
|
38
|
+
l.to_s(options)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
if a
|
42
|
+
# an arg delimiter was present, but without a label
|
43
|
+
# sanitize: remove trailing parenthetical remarks
|
44
|
+
target.gsub(/\s*\([^)]*\)$/, '')
|
45
|
+
else
|
46
|
+
target
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def target
|
52
|
+
if t
|
53
|
+
t.text_value
|
54
|
+
else
|
55
|
+
''
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
#-- defaults ++
|
60
|
+
def t #:nodoc:
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
|
64
|
+
def a #:nodoc:
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
|
68
|
+
def l #:nodoc:
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class ExternalLink < ParseNode
|
74
|
+
def to_html( options = {} )
|
75
|
+
if l
|
76
|
+
"<a href='#{target}'>#{label(:html, options)}</a>"
|
77
|
+
else
|
78
|
+
f = options[:footnotes]
|
79
|
+
if f
|
80
|
+
n = f.add( target )
|
81
|
+
"<a href='#{target}'>[#{n}]</a>"
|
82
|
+
else
|
83
|
+
"<a href='#{target}'></a>"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def to_s( options = {} )
|
89
|
+
f = options[:footnotes]
|
90
|
+
if l
|
91
|
+
if f
|
92
|
+
n = f.add( target, label(:text, options) )
|
93
|
+
"#{label(:text, options)} [#{n}]"
|
94
|
+
else
|
95
|
+
"#{label(:text, options)} [#{target}]"
|
96
|
+
end
|
97
|
+
else
|
98
|
+
if f
|
99
|
+
n = f.add( target )
|
100
|
+
"[#{n}]"
|
101
|
+
else
|
102
|
+
target
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def label( format, options = {} )
|
108
|
+
if l
|
109
|
+
case format
|
110
|
+
when :html
|
111
|
+
l.to_html(options)
|
112
|
+
else
|
113
|
+
l.to_s(options)
|
114
|
+
end
|
115
|
+
else
|
116
|
+
''
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def target
|
121
|
+
if t
|
122
|
+
t.text_value
|
123
|
+
else
|
124
|
+
''
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
#-- defaults ++
|
129
|
+
def t #:nodoc:
|
130
|
+
nil
|
131
|
+
end
|
132
|
+
|
133
|
+
def l #:nodoc:
|
134
|
+
nil
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class URL < ParseNode
|
139
|
+
# TODO: these should output links just like "[url]". The link tags
|
140
|
+
# shouldn't call these methods, these are called when the URL is not in a
|
141
|
+
# link. The link templates should grab the URL themselves.
|
142
|
+
def to_html( options = {} )
|
143
|
+
text_value
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_s( options = {} )
|
147
|
+
text_value
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class Protocol < ParseNode
|
152
|
+
end
|
153
|
+
end
|
data/lib/marker/lists.rb
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2009 Ryan Blue.
|
3
|
+
# Distributed under the terms of the GNU General Public License (GPL).
|
4
|
+
# See the LICENSE file for further information on the GPL.
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'marker/common'
|
8
|
+
|
9
|
+
module Marker #:nodoc:
|
10
|
+
# used to collect list lines into lists structured hierarchically, like in HTML
|
11
|
+
class ListBuilder
|
12
|
+
attr_reader :tag, :contents, :attrs
|
13
|
+
|
14
|
+
def initialize( contents, tag, attrs = {} )
|
15
|
+
@contents = [contents].flatten
|
16
|
+
@tag = tag
|
17
|
+
@attrs = attrs
|
18
|
+
end
|
19
|
+
|
20
|
+
# returns true if the l has the same tag
|
21
|
+
def ===( l )
|
22
|
+
( l.is_a? self.class and tag == l.tag )
|
23
|
+
end
|
24
|
+
|
25
|
+
def <<( l )
|
26
|
+
last = contents.last
|
27
|
+
|
28
|
+
if last and last === l
|
29
|
+
last += l
|
30
|
+
else
|
31
|
+
contents << l
|
32
|
+
end
|
33
|
+
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def +( l )
|
38
|
+
l.contents.each { |i| self << i } if self === l
|
39
|
+
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_html( options = {} )
|
44
|
+
if tag
|
45
|
+
"<#{tag}" +
|
46
|
+
( attrs.any?? ' ' : '' ) +
|
47
|
+
attrs.map { |k, v|
|
48
|
+
"#{k}='#{v}'"
|
49
|
+
}.join(' ') +
|
50
|
+
">" +
|
51
|
+
contents.map { |i|
|
52
|
+
i.to_html(options)
|
53
|
+
}.join +
|
54
|
+
"</#{tag}>"
|
55
|
+
else
|
56
|
+
contents.map { |i|
|
57
|
+
i.to_html(options)
|
58
|
+
}.join
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_s( options = {} )
|
63
|
+
strs = []
|
64
|
+
contents.each_with_index { |i, ind|
|
65
|
+
strs << i.to_s( options.merge(
|
66
|
+
:indent => ( options[:indent] || 0 ) + ( tag ? 1 : 0 ),
|
67
|
+
:num => ind + 1
|
68
|
+
) )
|
69
|
+
}
|
70
|
+
strs.join("\n")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class List < RecursiveList
|
75
|
+
def to_html( options = {} )
|
76
|
+
l = ListBuilder.new( [], nil )
|
77
|
+
to_a.each do |item|
|
78
|
+
l << item.structure
|
79
|
+
end
|
80
|
+
l.to_html(options)
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_s( options = {} )
|
84
|
+
l = ListBuilder.new( [], nil )
|
85
|
+
to_a.each do |item|
|
86
|
+
l << item.structure
|
87
|
+
end
|
88
|
+
l.to_s(options)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class Bulleted < ParseNode
|
93
|
+
def to_html( options = {} )
|
94
|
+
"<li>#{phrase.to_html(options)}</li>"
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_s( options = {} )
|
98
|
+
indent = (options[:indent] || 0)
|
99
|
+
' ' * (indent > 0 ? indent - 1 : 0) +
|
100
|
+
' * ' + phrase.to_s( options )
|
101
|
+
end
|
102
|
+
|
103
|
+
def structure
|
104
|
+
if phrase
|
105
|
+
ListBuilder.new( self, :ul )
|
106
|
+
else
|
107
|
+
ListBuilder.new( list_item.structure, :ul )
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
#-- defaults ++
|
112
|
+
def phrase
|
113
|
+
nil
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class Numbered < ParseNode
|
118
|
+
def to_html( options = {} )
|
119
|
+
"<li>#{phrase.to_html(options)}</li>"
|
120
|
+
end
|
121
|
+
|
122
|
+
def to_s( options = {} )
|
123
|
+
indent = (options[:indent] || 0)
|
124
|
+
' ' * (indent > 0 ? indent - 1 : 0) +
|
125
|
+
"#{'%2d' % options[:num]}. #{phrase.to_s( options )}"
|
126
|
+
end
|
127
|
+
|
128
|
+
def structure
|
129
|
+
if phrase
|
130
|
+
ListBuilder.new( self, :ol )
|
131
|
+
else
|
132
|
+
ListBuilder.new( list_item.structure, :ol )
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
#-- defaults ++
|
137
|
+
def phrase
|
138
|
+
nil
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
class Indented < ParseNode
|
143
|
+
def to_html( options = {} )
|
144
|
+
"<div>#{phrase.to_html(options)}</div>"
|
145
|
+
end
|
146
|
+
|
147
|
+
def to_s( options = {} )
|
148
|
+
indent = (options[:indent] || 0)
|
149
|
+
' ' * (indent > 0 ? indent : 0) +
|
150
|
+
phrase.to_s(options)
|
151
|
+
end
|
152
|
+
|
153
|
+
def structure
|
154
|
+
if phrase
|
155
|
+
ListBuilder.new( self, :div, :class => 'indent' )
|
156
|
+
else
|
157
|
+
ListBuilder.new( list_item.structure, :div, :class => 'indent' )
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
#-- defaults ++
|
162
|
+
def phrase
|
163
|
+
nil
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class Definition < ParseNode
|
168
|
+
def to_html( options = {} )
|
169
|
+
"<dt>#{term.to_html(options)}</dt>" +
|
170
|
+
( definition ? "<dd>#{definition.to_html(options)}</dd>" : "" )
|
171
|
+
end
|
172
|
+
|
173
|
+
def to_s( options = {} )
|
174
|
+
indent = (options[:indent] || 0)
|
175
|
+
' ' * (indent > 0 ? indent - 1: 0) +
|
176
|
+
"#{term.to_s(options)} :: #{definition.to_s(options)}"
|
177
|
+
end
|
178
|
+
|
179
|
+
def structure
|
180
|
+
ListBuilder.new( self, :dl )
|
181
|
+
end
|
182
|
+
|
183
|
+
#-- defaults ++
|
184
|
+
def definition
|
185
|
+
nil
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2009 Ryan Blue.
|
3
|
+
# Distributed under the terms of the GNU General Public License (GPL).
|
4
|
+
# See the LICENSE file for further information on the GPL.
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'marker/common'
|
8
|
+
|
9
|
+
module Marker #:nodoc:
|
10
|
+
class Markup < RecursiveList
|
11
|
+
def to_html( options = {} )
|
12
|
+
options = make_options( options )
|
13
|
+
|
14
|
+
[
|
15
|
+
to_a.map{ |b|
|
16
|
+
b.to_html(options)
|
17
|
+
}, options[:footnotes].to_html( options )
|
18
|
+
].flatten.join("\n")
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s( options = {} )
|
22
|
+
options = make_options( options )
|
23
|
+
|
24
|
+
[
|
25
|
+
to_a.map{ |b|
|
26
|
+
b.to_s(options)
|
27
|
+
}, options[:footnotes].to_s( options )
|
28
|
+
].flatten.join("\n")
|
29
|
+
end
|
30
|
+
|
31
|
+
def make_options( user_options )
|
32
|
+
o = Marker.render_options.dup
|
33
|
+
o.merge!( :link_base => Marker.link_base )
|
34
|
+
o.merge!( :footnotes => Footnotes.new ) unless user_options[:nofootnotes]
|
35
|
+
o.merge!( user_options )
|
36
|
+
o
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Footnotes
|
41
|
+
def notes
|
42
|
+
@notes ||= []
|
43
|
+
end
|
44
|
+
|
45
|
+
def add( *args )
|
46
|
+
notes << args
|
47
|
+
notes.size
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_html( options = {} )
|
51
|
+
return "" unless notes.any?
|
52
|
+
|
53
|
+
"<ol>" +
|
54
|
+
notes.map { |n|
|
55
|
+
target = n.shift
|
56
|
+
if n.any?
|
57
|
+
"<li><a href='#{target}'>#{n.join(' ')}</a></li>"
|
58
|
+
else
|
59
|
+
"<li><a href='#{target}'>#{target}</a></li>"
|
60
|
+
end
|
61
|
+
}.join +
|
62
|
+
"</ol>"
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_s( options = {} )
|
66
|
+
return "" unless notes.any?
|
67
|
+
|
68
|
+
s = "\n"
|
69
|
+
notes.each_with_index{ |n, i|
|
70
|
+
target = n.shift
|
71
|
+
if n.any?
|
72
|
+
s << "#{'%2d' % (i + 1)}. #{n.join(' ')}: #{target}\n"
|
73
|
+
else
|
74
|
+
s << "#{'%2d' % (i + 1)}. #{target}\n"
|
75
|
+
end
|
76
|
+
}
|
77
|
+
|
78
|
+
s
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2009 Ryan Blue.
|
3
|
+
# Distributed under the terms of the GNU General Public License (GPL).
|
4
|
+
# See the LICENSE file for further information on the GPL.
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'marker/common'
|
8
|
+
|
9
|
+
module Marker #:nodoc:
|
10
|
+
class Template < ParseNode
|
11
|
+
def to_html( options = {} )
|
12
|
+
render( :html, options )
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s( options = {} )
|
16
|
+
render( :text, options )
|
17
|
+
end
|
18
|
+
|
19
|
+
def render( format, options = {} )
|
20
|
+
Marker.templates.send( target, format, *arg_list( format, options ) )
|
21
|
+
end
|
22
|
+
|
23
|
+
def target
|
24
|
+
# sanitize the string to get a method name
|
25
|
+
t.text_value.gsub(/\s/, '_').to_sym
|
26
|
+
end
|
27
|
+
|
28
|
+
def arg_list( format, options )
|
29
|
+
( args ? args.to_arg_list( format, options ) : [[], {}] )
|
30
|
+
end
|
31
|
+
|
32
|
+
#-- defaults ++
|
33
|
+
def t #:nodoc:
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def args #:nodoc:
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class Arguments < RecursiveList
|
43
|
+
def to_arg_list( format, options = {} )
|
44
|
+
pos_params = []
|
45
|
+
named_params = {}
|
46
|
+
|
47
|
+
case format
|
48
|
+
when :html
|
49
|
+
to_a.each do |a|
|
50
|
+
next unless a
|
51
|
+
if a.name
|
52
|
+
named_params[a.name.to_html( options )] = a.val.to_html( options )
|
53
|
+
else
|
54
|
+
pos_params << a.val.to_html( options )
|
55
|
+
end
|
56
|
+
end
|
57
|
+
else
|
58
|
+
to_a.each do |a|
|
59
|
+
next unless a
|
60
|
+
if a.name
|
61
|
+
named_params[a.name.to_s( options )] = a.val.to_s( options )
|
62
|
+
else
|
63
|
+
pos_params << a.val.to_s( options )
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
[pos_params, named_params]
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_html( options = {} )
|
72
|
+
to_a.map { |a|
|
73
|
+
a ? a.to_html(options) : ''
|
74
|
+
}.join(', ')
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_s( options = {} )
|
78
|
+
to_a.map { |a|
|
79
|
+
a ? a.to_s(options) : ''
|
80
|
+
}.join(', ')
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class Argument < ParseNode
|
85
|
+
def to_html( options = {} )
|
86
|
+
to_s
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_s( options = {} )
|
90
|
+
( name ? "'#{name}' => '#{val}'" : "'#{val}'" )
|
91
|
+
end
|
92
|
+
|
93
|
+
#-- defaults ++
|
94
|
+
def name #:nodoc:
|
95
|
+
nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# A set of basic templates for rendering
|
100
|
+
module DefaultTemplates
|
101
|
+
def self.method_missing( sym, *args )
|
102
|
+
"render:#{sym}( #{args.map(&:inspect).join(', ')} )"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/lib/marker/text.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2009 Ryan Blue.
|
3
|
+
# Distributed under the terms of the GNU General Public License (GPL).
|
4
|
+
# See the LICENSE file for further information on the GPL.
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'marker/common'
|
8
|
+
|
9
|
+
module Marker #:nodoc:
|
10
|
+
class Paragraph < RecursiveList
|
11
|
+
def to_html( options = {} )
|
12
|
+
'<p>' +
|
13
|
+
to_a.map { |p|
|
14
|
+
p.to_html(options)
|
15
|
+
}.join(' ') +
|
16
|
+
'</p>'
|
17
|
+
end
|
18
|
+
|
19
|
+
# TODO: add wordwrap
|
20
|
+
def to_s( options = {} )
|
21
|
+
to_a.map { |p|
|
22
|
+
p.to_s(options)
|
23
|
+
}.join(' ')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Phrase < RecursiveList
|
28
|
+
def to_html( options = {} )
|
29
|
+
s = h.to_html(options)
|
30
|
+
s << ' ' if space?
|
31
|
+
s << r.to_html(options) if r
|
32
|
+
s
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s( options = {} )
|
36
|
+
s = h.to_s(options)
|
37
|
+
s << ' ' if space?
|
38
|
+
s << r.to_s(options) if r
|
39
|
+
s
|
40
|
+
end
|
41
|
+
|
42
|
+
# returns true if there was white space after the first "word"
|
43
|
+
def space?
|
44
|
+
(ws and ws.present?) or (aws and aws.present?)
|
45
|
+
end
|
46
|
+
|
47
|
+
#-- defaults ++
|
48
|
+
def ws
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def aws
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class Word < ParseNode
|
58
|
+
def to_html( options = {} )
|
59
|
+
text_value
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_s( options = {} )
|
63
|
+
text_value
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class Delimiter < ParseNode
|
68
|
+
def to_html( options = {} )
|
69
|
+
text_value
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_s( options = {} )
|
73
|
+
text_value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Bold < ParseNode
|
78
|
+
def to_html( options = {} )
|
79
|
+
"<b>#{bold_enclosed_text.to_html(options)}</b>"
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_s( options = {} )
|
83
|
+
"*#{bold_enclosed_text.to_s(options)}*"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class Italic < ParseNode
|
88
|
+
def to_html( options = {} )
|
89
|
+
"<i>#{italic_enclosed_text.to_html(options)}</i>"
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_s( options = {} )
|
93
|
+
"/#{italic_enclosed_text.to_s(options)}/"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2009 Ryan Blue.
|
3
|
+
# Distributed under the terms of the GNU General Public License (GPL).
|
4
|
+
# See the LICENSE file for further information on the GPL.
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'marker/common'
|
8
|
+
|
9
|
+
module Marker #:nodoc:
|
10
|
+
class VerbatimArea < RecursiveList
|
11
|
+
def to_html( options = {} )
|
12
|
+
"<pre>\n" +
|
13
|
+
to_a.map { |l|
|
14
|
+
l.to_html(options)
|
15
|
+
}.join("\n") +
|
16
|
+
"\n</pre>"
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s( options = {} )
|
20
|
+
"-- \n" +
|
21
|
+
to_a.map { |l|
|
22
|
+
l.to_s(options)
|
23
|
+
}.join("\n") +
|
24
|
+
"\n-- "
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Verbatim < ParseNode
|
29
|
+
def to_html( options = {} )
|
30
|
+
v.text_value
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s( options = {} )
|
34
|
+
v.text_value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class HorizRule < ParseNode
|
39
|
+
def to_html( options = {} )
|
40
|
+
"<hr />"
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s( options = {} )
|
44
|
+
width = options[:width] || 80
|
45
|
+
"-" * width
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|