junebug 0.0.14 → 0.0.15
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/CHANGELOG +8 -0
- data/README +7 -7
- data/RELEASE_NOTES +7 -0
- data/Rakefile +6 -3
- data/bin/junebug +0 -5
- data/deploy/static/style/base.css +12 -3
- data/deploy/wiki +1 -2
- data/lib/junebug.rb +2 -0
- data/lib/junebug/controllers.rb +12 -12
- data/lib/junebug/generator.rb +18 -1
- data/lib/junebug/models.rb +7 -3
- data/lib/junebug/redcloth.rb +5 -0
- data/lib/junebug/redcloth/all_formats.rb +4 -0
- data/lib/junebug/redcloth/base.rb +674 -0
- data/lib/junebug/redcloth/docbook.rb +1006 -0
- data/lib/junebug/redcloth/markdown.rb +138 -0
- data/lib/junebug/redcloth/textile.rb +449 -0
- data/lib/junebug/views.rb +3 -3
- data/test/wiki_test.rb +128 -40
- metadata +11 -3
@@ -0,0 +1,138 @@
|
|
1
|
+
unless defined? RedCloth
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
require 'base'
|
4
|
+
end
|
5
|
+
|
6
|
+
class RedCloth < String
|
7
|
+
|
8
|
+
DEFAULT_RULES << :markdown
|
9
|
+
|
10
|
+
# == Markdown
|
11
|
+
#
|
12
|
+
# refs_markdown:: Markdown references (for example: [hobix]: http://hobix.com/)
|
13
|
+
# block_markdown_setext:: Markdown setext headers
|
14
|
+
# block_markdown_atx:: Markdown atx headers
|
15
|
+
# block_markdown_rule:: Markdown horizontal rules
|
16
|
+
# block_markdown_bq:: Markdown blockquotes
|
17
|
+
# block_markdown_lists:: Markdown lists
|
18
|
+
# inline_markdown_link:: Markdown links
|
19
|
+
#
|
20
|
+
|
21
|
+
#######
|
22
|
+
private
|
23
|
+
#######
|
24
|
+
|
25
|
+
def block_markdown_setext( text )
|
26
|
+
if text =~ SETEXT_RE
|
27
|
+
tag = if $2 == "="; "h1"; else; "h2"; end
|
28
|
+
blk, cont = "<#{ tag }>#{ $1 }</#{ tag }>", $'
|
29
|
+
blocks cont
|
30
|
+
text.replace( blk + cont )
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def block_markdown_atx( text )
|
35
|
+
if text =~ ATX_RE
|
36
|
+
tag = "h#{ $1.length }"
|
37
|
+
blk, cont = "<#{ tag }>#{ $2 }</#{ tag }>\n\n", $'
|
38
|
+
blocks cont
|
39
|
+
text.replace( blk + cont )
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
MARKDOWN_BQ_RE = /\A(^ *> ?.+$(.+\n)*\n*)+/m
|
44
|
+
|
45
|
+
def block_markdown_bq( text )
|
46
|
+
text.gsub!( MARKDOWN_BQ_RE ) do |blk|
|
47
|
+
blk.gsub!( /^ *> ?/, '' )
|
48
|
+
flush_left blk
|
49
|
+
blocks blk
|
50
|
+
blk.gsub!( /^(\S)/, "\t\\1" )
|
51
|
+
"<blockquote>\n#{ blk }\n</blockquote>\n\n"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
MARKDOWN_RULE_RE = /^(.*)( ?[#{
|
56
|
+
['*', '-', '_'].collect { |ch| Regexp::quote( ch ) }.join
|
57
|
+
}] ?){3,}(.*)$/
|
58
|
+
|
59
|
+
def block_markdown_rule( text )
|
60
|
+
text.gsub!( MARKDOWN_RULE_RE ) do |blk|
|
61
|
+
if $3.empty? && $1 =~ /[#{['*', '-', '_'].collect { |ch| Regexp::quote( ch ) }.join}]*/
|
62
|
+
"<hr />"
|
63
|
+
else
|
64
|
+
blk
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# XXX TODO XXX
|
70
|
+
def block_markdown_lists( text )
|
71
|
+
end
|
72
|
+
|
73
|
+
def inline_markdown_link( text )
|
74
|
+
end
|
75
|
+
|
76
|
+
MARKDOWN_REFLINK_RE = /
|
77
|
+
\[([^\[\]]+)\] # $text
|
78
|
+
[ ]? # opt. space
|
79
|
+
(?:\n[ ]*)? # one optional newline followed by spaces
|
80
|
+
\[(.*?)\] # $id
|
81
|
+
/x
|
82
|
+
|
83
|
+
def inline_markdown_reflink( text )
|
84
|
+
text.gsub!( MARKDOWN_REFLINK_RE ) do |m|
|
85
|
+
text, id = $~[1..2]
|
86
|
+
|
87
|
+
if id.empty?
|
88
|
+
url, title = check_refs( text )
|
89
|
+
else
|
90
|
+
url, title = check_refs( id )
|
91
|
+
end
|
92
|
+
|
93
|
+
atts = " href=\"#{ url }\""
|
94
|
+
atts << " title=\"#{ title }\"" if title
|
95
|
+
atts = shelve( atts )
|
96
|
+
|
97
|
+
"<a#{ atts }>#{ text }</a>"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
MARKDOWN_LINK_RE = /
|
102
|
+
\[([^\[\]]+)\] # $text
|
103
|
+
\( # open paren
|
104
|
+
[ \t]* # opt space
|
105
|
+
<?(.+?)>? # $href
|
106
|
+
[ \t]* # opt space
|
107
|
+
(?: # whole title
|
108
|
+
(['"]) # $quote
|
109
|
+
(.*?) # $title
|
110
|
+
\3 # matching quote
|
111
|
+
)? # title is optional
|
112
|
+
\)
|
113
|
+
/x
|
114
|
+
|
115
|
+
def inline_markdown_link( text )
|
116
|
+
text.gsub!( MARKDOWN_LINK_RE ) do |m|
|
117
|
+
text, url, quote, title = $~[1..4]
|
118
|
+
|
119
|
+
atts = " href=\"#{ url }\""
|
120
|
+
atts << " title=\"#{ title }\"" if title
|
121
|
+
atts = shelve( atts )
|
122
|
+
|
123
|
+
"<a#{ atts }>#{ text }</a>"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
MARKDOWN_REFS_RE = /(^ *)\[([^\n]+?)\]:\s+<?(#{HYPERLINK})>?(?:\s+"((?:[^"]|\\")+)")?(?=\s|$)/m
|
128
|
+
|
129
|
+
def refs_markdown( text )
|
130
|
+
text.gsub!( MARKDOWN_REFS_RE ) do |m|
|
131
|
+
flag, url = $~[2..3]
|
132
|
+
title = $~[6]
|
133
|
+
@urlrefs[flag.downcase] = [url, title]
|
134
|
+
nil
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
@@ -0,0 +1,449 @@
|
|
1
|
+
unless defined? RedCloth
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
require 'base'
|
4
|
+
end
|
5
|
+
|
6
|
+
class RedCloth < String
|
7
|
+
|
8
|
+
DEFAULT_RULES << :textile
|
9
|
+
|
10
|
+
#
|
11
|
+
# == Textile Rules
|
12
|
+
#
|
13
|
+
# The following textile rules can be set individually. Or add the complete
|
14
|
+
# set of rules with the single :textile rule, which supplies the rule set in
|
15
|
+
# the following precedence:
|
16
|
+
#
|
17
|
+
# refs_textile:: Textile references (i.e. [hobix]http://hobix.com/)
|
18
|
+
# block_textile_table:: Textile table block structures
|
19
|
+
# block_textile_lists:: Textile list structures
|
20
|
+
# block_textile_prefix:: Textile blocks with prefixes (i.e. bq., h2., etc.)
|
21
|
+
# block_textile_defs:: Textile definition lists
|
22
|
+
# inline_textile_image:: Textile inline images
|
23
|
+
# inline_textile_link:: Textile inline links
|
24
|
+
# inline_textile_span:: Textile inline spans
|
25
|
+
# glyphs_textile:: Textile entities (such as em-dashes and smart quotes)
|
26
|
+
#
|
27
|
+
|
28
|
+
#######
|
29
|
+
private
|
30
|
+
#######
|
31
|
+
#
|
32
|
+
# Mapping of 8-bit ASCII codes to HTML numerical entity equivalents.
|
33
|
+
# (from PyTextile)
|
34
|
+
#
|
35
|
+
TEXTILE_TAGS =
|
36
|
+
|
37
|
+
[[128, 8364], [129, 0], [130, 8218], [131, 402], [132, 8222], [133, 8230],
|
38
|
+
[134, 8224], [135, 8225], [136, 710], [137, 8240], [138, 352], [139, 8249],
|
39
|
+
[140, 338], [141, 0], [142, 0], [143, 0], [144, 0], [145, 8216], [146, 8217],
|
40
|
+
[147, 8220], [148, 8221], [149, 8226], [150, 8211], [151, 8212], [152, 732],
|
41
|
+
[153, 8482], [154, 353], [155, 8250], [156, 339], [157, 0], [158, 0], [159, 376]].
|
42
|
+
|
43
|
+
collect! do |a, b|
|
44
|
+
[a.chr, ( b.zero? and "" or "&##{ b };" )]
|
45
|
+
end
|
46
|
+
|
47
|
+
def textile_pre_process(text)
|
48
|
+
{'w' => 'warning', 'n' => 'note', 'c' => 'comment', 'pro' => 'production', 'dt' => 'dt', 'dd' => 'dd'}.each do |char, word|
|
49
|
+
parts = text.split(/^\s*#{char}\./)
|
50
|
+
text.replace(parts.first + "\n" + parts[1..-1].map do |part|
|
51
|
+
if part =~ /\.#{char}\s*$/
|
52
|
+
"div(#{word})." + part.sub(/\.#{char}\s*$/, "div(#{word}). \n")
|
53
|
+
else
|
54
|
+
"#{char}.#{part}"
|
55
|
+
end
|
56
|
+
end.join("\n"))
|
57
|
+
|
58
|
+
self.class.class_eval %!
|
59
|
+
def textile_#{char}(tag, atts, cite, content)
|
60
|
+
textile_p('p', %{ class=#{word.inspect}}, cite, content)
|
61
|
+
end
|
62
|
+
!
|
63
|
+
end
|
64
|
+
{'bq' => 'blockquote'}.each do |char, word|
|
65
|
+
parts = text.split(/^\s*#{char}\./)
|
66
|
+
text.replace(parts.first + "\n" + parts[1..-1].map do |part|
|
67
|
+
if part =~ /\.#{char}\s*$/
|
68
|
+
"div(#{word})." + part.sub(/\.#{char}\s*$/, "div(#{word}). ")
|
69
|
+
else
|
70
|
+
"#{char}.#{part}"
|
71
|
+
end
|
72
|
+
end.join("\n"))
|
73
|
+
end
|
74
|
+
|
75
|
+
text.gsub!( BACKTICK_CODE_RE ) do |m|
|
76
|
+
before,lang,code,after = $~[1..4]
|
77
|
+
lang = " lang=\"#{ lang }\"" if lang
|
78
|
+
rip_offtags( "#{ before }<pre><code#{ lang }>#{ code.gsub(/\\\`\`\`/,'```') }</code></pre>#{ after }" )
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def textile_post_process(text)
|
83
|
+
post_inline_textile_span(text)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Parses a Textile table block, building HTML from the result.
|
87
|
+
def block_textile_table( text )
|
88
|
+
text.gsub!( TABLE_RE ) do |matches|
|
89
|
+
|
90
|
+
caption, id, tatts, fullrow = $~[1..4]
|
91
|
+
tatts = pba( tatts, 'table' )
|
92
|
+
tatts = shelve( tatts ) if tatts
|
93
|
+
rows = []
|
94
|
+
|
95
|
+
fullrow.
|
96
|
+
split( /\|$/m ).
|
97
|
+
delete_if {|row|row.empty?}.
|
98
|
+
each do |row|
|
99
|
+
|
100
|
+
ratts, row = pba( $1, 'tr' ), $2 if row =~ /^(#{A}#{C}\. )(.*)/m
|
101
|
+
row << " "
|
102
|
+
|
103
|
+
cells = []
|
104
|
+
row.split( '|' ).each_with_index do |cell, i|
|
105
|
+
next if i == 0
|
106
|
+
|
107
|
+
ctyp = 'd'
|
108
|
+
ctyp = 'h' if cell =~ /^_/
|
109
|
+
|
110
|
+
catts = ''
|
111
|
+
catts, cell = pba( $1, 'td' ), $2 if cell =~ /^(_?#{S}#{A}#{C}\. ?)(.*)/
|
112
|
+
|
113
|
+
catts = shelve( catts ) if catts
|
114
|
+
cells << "\t\t\t<t#{ ctyp }#{ catts }>#{ cell.strip.empty? ? " " : row.split( '|' ).size-1 != i ? cell : cell[0...cell.length-1] }</t#{ ctyp }>"
|
115
|
+
end
|
116
|
+
ratts = shelve( ratts ) if ratts
|
117
|
+
rows << "\t\t<tr#{ ratts }>\n#{ cells.join( "\n" ) }\n\t\t</tr>"
|
118
|
+
end
|
119
|
+
caption = "\t<p class=\"caption\">#{caption}</p>\n" if caption
|
120
|
+
"#{caption}\t<table#{ tatts }>\n#{ rows.join( "\n" ) }\n\t</table>\n\n"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Parses Textile lists and generates HTML
|
125
|
+
def block_textile_lists( text )
|
126
|
+
orig_text = text.dup
|
127
|
+
|
128
|
+
# Take care of _*'s and _#'s to turn them into paragraphs
|
129
|
+
text.gsub!(/([\*#] )((.*?\n\s*_[\*#].*?)+)/) do |m|
|
130
|
+
"#{$1}<p>"+$2.split(/_[\*#]/).map{|w|w.strip}.delete_if{|w|w.empty?}.join("</p><p>")+"</p>"
|
131
|
+
end
|
132
|
+
|
133
|
+
@last_line ||= -1
|
134
|
+
|
135
|
+
text.gsub!( LISTS_RE ) do |match|
|
136
|
+
if text =~ /^#([_0-9]+).*/m
|
137
|
+
if $1 == $1.to_i.to_s # then it is a number, so use it
|
138
|
+
@last_line = $1.to_i - 2
|
139
|
+
end
|
140
|
+
else
|
141
|
+
@last_line = -1
|
142
|
+
end
|
143
|
+
lines = match.split( /\n/ )
|
144
|
+
depth = []
|
145
|
+
lines.each_with_index do |line, line_id|
|
146
|
+
if line =~ LISTS_CONTENT_RE
|
147
|
+
|
148
|
+
tl,continuation,atts,content = $~[1..4]
|
149
|
+
@last_line += 1 if tl.length == 1
|
150
|
+
|
151
|
+
unless depth.last.nil?
|
152
|
+
if depth.last.length > tl.length
|
153
|
+
(depth.length - 1).downto(0) do |i|
|
154
|
+
break if depth[i].length == tl.length
|
155
|
+
lines[line_id - 1] << "</li>\n#{"\t"*(depth.size-1)}</#{ lT( depth[i] ) }l>"
|
156
|
+
depth.pop
|
157
|
+
tab_in = true
|
158
|
+
end
|
159
|
+
end
|
160
|
+
if depth.last && depth.last.length == tl.length
|
161
|
+
lines[line_id - 1] << "</li>"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
unless depth.last == tl
|
165
|
+
depth << tl
|
166
|
+
atts = pba( atts )
|
167
|
+
atts << " start=\"#{@last_line + 1}\"" if lT(tl) == "o" && !continuation.empty? && @last_line > 0
|
168
|
+
atts = shelve( atts ) if atts
|
169
|
+
lines[line_id] = "#{"\t"*(depth.size-1)}<#{ lT(tl) }l#{ atts }>\n#{"\t"*depth.size}<li>#{ content }"
|
170
|
+
else
|
171
|
+
lines[line_id] = "#{"\t"*depth.size}<li>#{ content }"
|
172
|
+
end
|
173
|
+
elsif line =~ /^([_]+)(#{A}#{C}) (.*)$/m
|
174
|
+
@last_line += 1
|
175
|
+
tl = "u"
|
176
|
+
atts,content = $~[2..3]
|
177
|
+
|
178
|
+
unless depth.last.nil?
|
179
|
+
if depth.last.length > tl.length
|
180
|
+
(depth.length - 1).downto(0) do |i|
|
181
|
+
break if depth[i].length == tl.length
|
182
|
+
lines[line_id - 1] << "</li>\n#{"\t"*(depth.size-1)}</#{ lT( depth[i] ) }l>"
|
183
|
+
depth.pop
|
184
|
+
tab_in = true
|
185
|
+
end
|
186
|
+
end
|
187
|
+
if depth.last and depth.last.length == tl.length
|
188
|
+
lines[line_id - 1] << "</li>"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
unless depth.last == tl
|
192
|
+
depth << tl
|
193
|
+
atts = pba( atts )
|
194
|
+
atts = shelve( "#{atts} style=\"list-style-type:none;\"" )
|
195
|
+
lines[line_id] = "#{"\t"*(depth.size-1)}<#{ lT(tl) }l#{ atts }>\n#{"\t"*depth.size}<li>#{ content }"
|
196
|
+
else
|
197
|
+
lines[line_id] = "#{"\t"*depth.size}<li>#{ content }"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
if line_id == lines.length - 1
|
202
|
+
tabs = depth.size-1
|
203
|
+
depth.reverse.delete_if do |v|
|
204
|
+
lines[-1] << "</li>\n#{"\t"*tabs}</#{ lT( v ) }l>"
|
205
|
+
tabs -= 1
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
lines.join( "\n" )
|
210
|
+
end
|
211
|
+
|
212
|
+
text != orig_text
|
213
|
+
end
|
214
|
+
|
215
|
+
# Parses Textile definition lists and generates HTML
|
216
|
+
def block_textile_defs( text )
|
217
|
+
text.gsub!(/^-\s+(.*?):=(.*?)=:\s*$/m) do |m|
|
218
|
+
"- #{$1.strip} := <p>"+$2.split(/\n/).map{|w|w.strip}.delete_if{|w|w.empty?}.join("</p><p>")+"</p>"
|
219
|
+
end
|
220
|
+
|
221
|
+
text.gsub!( DEFS_RE ) do |match|
|
222
|
+
lines = match.split( /\n/ )
|
223
|
+
lines.each_with_index do |line, line_id|
|
224
|
+
if line =~ DEFS_CONTENT_RE
|
225
|
+
dl,continuation,dt,dd = $~[1..4]
|
226
|
+
|
227
|
+
atts = pba( atts )
|
228
|
+
atts = shelve( atts ) if atts
|
229
|
+
lines[line_id] = line_id == 0 ? "<dl#{ atts }>" : ""
|
230
|
+
lines[line_id] << "\n\t<dt>#{ dt.strip }</dt>\n\t<dd>#{ dd.strip }</dd>"
|
231
|
+
end
|
232
|
+
|
233
|
+
if line_id == lines.length - 1
|
234
|
+
lines[-1] << "\n</dl>"
|
235
|
+
end
|
236
|
+
end
|
237
|
+
lines.join( "\n" )
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def inline_textile_code( text )
|
242
|
+
text.gsub!( CODE_RE ) do |m|
|
243
|
+
before,lang,code,after = $~[1..4]
|
244
|
+
lang = " lang=\"#{ lang }\"" if lang
|
245
|
+
rip_offtags( "#{ before }<code#{ lang }>#{ code.gsub(/\\@(@?)/,'@\1') }</code>#{ after }" )
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def textile_bq( tag, atts, cite, content )
|
250
|
+
cite, cite_title = check_refs( cite )
|
251
|
+
cite = " cite=\"#{ cite }\"" if cite
|
252
|
+
atts = shelve( atts ) if atts
|
253
|
+
"\t<blockquote#{ cite }>\n\t\t<p#{ atts }>#{ content }</p>\n\t</blockquote>"
|
254
|
+
end
|
255
|
+
|
256
|
+
def textile_p( tag, atts, cite, content )
|
257
|
+
atts = shelve( atts ) if atts
|
258
|
+
"\t<#{ tag }#{ atts }>#{ content }</#{ tag }>"
|
259
|
+
end
|
260
|
+
|
261
|
+
alias textile_h1 textile_p
|
262
|
+
alias textile_h2 textile_p
|
263
|
+
alias textile_h3 textile_p
|
264
|
+
alias textile_h4 textile_p
|
265
|
+
alias textile_h5 textile_p
|
266
|
+
alias textile_h6 textile_p
|
267
|
+
|
268
|
+
def textile_fn_( tag, num, atts, cite, content )
|
269
|
+
atts << " id=\"fn#{ num }\""
|
270
|
+
content = "<sup>#{ num }</sup> #{ content }"
|
271
|
+
atts = shelve( atts ) if atts
|
272
|
+
"\t<p#{ atts }>#{ content }</p>"
|
273
|
+
end
|
274
|
+
|
275
|
+
def textile_ch( tag, atts, cite, content )
|
276
|
+
textile_p("h1", atts, cite, content)
|
277
|
+
end
|
278
|
+
|
279
|
+
def block_textile_prefix( text )
|
280
|
+
if text =~ BLOCK_RE
|
281
|
+
tag,tagpre,num,atts,cite,content = $~[1..6]
|
282
|
+
atts = pba( atts )
|
283
|
+
|
284
|
+
# pass to prefix handler
|
285
|
+
if respond_to? "textile_#{ tag }", true
|
286
|
+
text.gsub!( $&, method( "textile_#{ tag }" ).call( tag, atts, cite, content ) )
|
287
|
+
elsif respond_to? "textile_#{ tagpre }_", true
|
288
|
+
text.gsub!( $&, method( "textile_#{ tagpre }_" ).call( tagpre, num, atts, cite, content ) )
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def inline_textile_span( text )
|
294
|
+
QTAGS.each do |qtag_rc, ht, qtag_re, rtype, escaped_re|
|
295
|
+
text.gsub!( qtag_re ) do |m|
|
296
|
+
|
297
|
+
case rtype
|
298
|
+
when :limit
|
299
|
+
sta,qtag,atts,cite,content = $~[1..5]
|
300
|
+
else
|
301
|
+
qtag,atts,cite,content = $~[1..4]
|
302
|
+
sta = ''
|
303
|
+
end
|
304
|
+
atts = pba( atts )
|
305
|
+
atts << " cite=\"#{ cite }\"" if cite
|
306
|
+
atts = shelve( atts ) if atts
|
307
|
+
|
308
|
+
"#{ sta }<#{ ht }#{ atts }>#{ content }</#{ ht }>"
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
def post_inline_textile_span( text )
|
314
|
+
QTAGS.each do |qtag_rc, ht, qtag_re, rtype, escaped_re|
|
315
|
+
text.gsub!( escaped_re ) do |m|
|
316
|
+
|
317
|
+
case rtype
|
318
|
+
when :limit
|
319
|
+
sta,qtag,atts,cite,content = $~[1..5]
|
320
|
+
else
|
321
|
+
qtag,atts,cite,content = $~[1..4]
|
322
|
+
sta = ''
|
323
|
+
end
|
324
|
+
atts = pba( atts )
|
325
|
+
atts << " cite=\"#{ cite }\"" if cite
|
326
|
+
|
327
|
+
"#{ sta }<#{ ht }#{ atts }>#{ content }</#{ ht }>"
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
def inline_textile_link( text )
|
333
|
+
text.gsub!( LINK_RE ) do |m|
|
334
|
+
pre,atts,text,title,url,slash,post = $~[1..7]
|
335
|
+
|
336
|
+
url, url_title = check_refs( url )
|
337
|
+
title ||= url_title
|
338
|
+
|
339
|
+
atts = pba( atts )
|
340
|
+
atts = " href=\"#{ url }#{ slash }\"#{ atts }"
|
341
|
+
atts << " title=\"#{ title }\"" if title
|
342
|
+
atts = shelve( atts ) if atts
|
343
|
+
|
344
|
+
"#{ pre }<a#{ atts }>#{ text }</a>#{ post }"
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
TEXTILE_REFS_RE = /(^ *)\[([^\n\[]+?)\](#{HYPERLINK})(?=\s|$)/
|
349
|
+
|
350
|
+
def refs_textile( text )
|
351
|
+
text.gsub!( TEXTILE_REFS_RE ) do |m|
|
352
|
+
flag, url = $~[2..3]
|
353
|
+
@urlrefs[flag.downcase] = [url, nil]
|
354
|
+
nil
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
def inline_textile_image( text )
|
359
|
+
text.gsub!( IMAGE_RE ) do |m|
|
360
|
+
stln,algn,atts,url,title,href,href_a1,href_a2 = $~[1..8]
|
361
|
+
atts = pba( atts )
|
362
|
+
atts = " src=\"#{ url }\"#{ atts }"
|
363
|
+
atts << " title=\"#{ title }\"" if title
|
364
|
+
atts << " alt=\"#{ title }\""
|
365
|
+
# size = @getimagesize($url);
|
366
|
+
# if($size) $atts.= " $size[3]";
|
367
|
+
|
368
|
+
href, alt_title = check_refs( href ) if href
|
369
|
+
url, url_title = check_refs( url )
|
370
|
+
|
371
|
+
out = ''
|
372
|
+
out << "<a#{ shelve( " href=\"#{ href }\"" ) }>" if href
|
373
|
+
out << "<img#{ shelve( atts ) } />"
|
374
|
+
out << "</a>#{ href_a1 }#{ href_a2 }" if href
|
375
|
+
|
376
|
+
if algn
|
377
|
+
algn = h_align( algn )
|
378
|
+
if stln == "<p>"
|
379
|
+
out = "<p style=\"float:#{ algn }\">#{ out }"
|
380
|
+
else
|
381
|
+
out = "#{ stln }<div style=\"float:#{ algn }\">#{ out }</div>"
|
382
|
+
end
|
383
|
+
else
|
384
|
+
out = stln + out
|
385
|
+
end
|
386
|
+
|
387
|
+
out
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
def no_textile( text )
|
392
|
+
text.gsub!( /(^|\s)(\\?)==([^=]+.*?)\2==(\s|$)?/ ) do |m|
|
393
|
+
$2.empty? ? "#{$1}<notextile>#{$3}</notextile>#{$4}" : "#{$1}==#{$3}==#{$4}"
|
394
|
+
end
|
395
|
+
text.gsub!( /^ *(\\?)==([^=]+.*?)\1==/m ) do |m|
|
396
|
+
$1.empty? ? "<notextile>#{$2}</notextile>" : "==#{$2}=="
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
def glyphs_textile( text, level = 0 )
|
401
|
+
if text !~ HASTAG_MATCH
|
402
|
+
pgl text
|
403
|
+
footnote_ref text
|
404
|
+
else
|
405
|
+
codepre = 0
|
406
|
+
text.gsub!( ALLTAG_MATCH ) do |line|
|
407
|
+
## matches are off if we're between <code>, <pre> etc.
|
408
|
+
if $1
|
409
|
+
if line =~ OFFTAG_OPEN
|
410
|
+
codepre += 1
|
411
|
+
elsif line =~ OFFTAG_CLOSE
|
412
|
+
codepre -= 1
|
413
|
+
codepre = 0 if codepre < 0
|
414
|
+
end
|
415
|
+
elsif codepre.zero?
|
416
|
+
glyphs_textile( line, level + 1 )
|
417
|
+
else
|
418
|
+
htmlesc( line, :NoQuotes )
|
419
|
+
end
|
420
|
+
## p [level, codepre, orig_line, line]
|
421
|
+
|
422
|
+
line
|
423
|
+
end
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
def textile_popup_help( name, windowW, windowH )
|
428
|
+
' <a target="_blank" href="http://hobix.com/textile/#' + helpvar + '" onclick="window.open(this.href, \'popupwindow\', \'width=' + windowW + ',height=' + windowH + ',scrollbars,resizable\'); return false;">' + name + '</a><br />'
|
429
|
+
end
|
430
|
+
|
431
|
+
# Turns all urls into clickable links.
|
432
|
+
# Taken from ActionPack's ActionView
|
433
|
+
def inline_textile_autolink_urls(text)
|
434
|
+
text.gsub!(AUTO_LINK_RE) do
|
435
|
+
all, a, b, c, d = $&, $1, $2, $3, $5
|
436
|
+
if a =~ /<a\s/i # don't replace URL's that are already linked
|
437
|
+
all
|
438
|
+
else
|
439
|
+
%(#{a}<a href="#{b=="www."?"http://www.":b}#{c}">#{b}#{c}</a>#{d})
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
# Turns all email addresses into clickable links.
|
445
|
+
def inline_textile_autolink_emails(text)
|
446
|
+
text.gsub!(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/, '<a href="mailto:\1">\1</a>')
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|