ubbparser 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/ubbparser.rb +447 -0
- metadata +45 -0
data/lib/ubbparser.rb
ADDED
@@ -0,0 +1,447 @@
|
|
1
|
+
require "strscan"
|
2
|
+
require "securerandom"
|
3
|
+
|
4
|
+
# The UBBParser module converts UBB code into HTML. The parser is flexibel
|
5
|
+
# and adding new ubb codes is as easy as writing methods.
|
6
|
+
# Author:: Taco Jan Osinga, Osinga Software
|
7
|
+
#
|
8
|
+
# You can create your own ubbcodes by opening the module UBBParser and adding a method called render_xxx,
|
9
|
+
# where xxx is your ubb code of choice. The method should have the following arguments:
|
10
|
+
# (inner_text, attributes = {}, parse_options = {})
|
11
|
+
# inner_text:: Contains the text that's found between the opening and the closing tag.
|
12
|
+
# attributes:: A hash containing all the key-value attributes that are given.
|
13
|
+
# parse_options:: A hash containing the same parse_options that are used when UBBParser.parse() is called.
|
14
|
+
#
|
15
|
+
# *Example*
|
16
|
+
# The following example adds the ubb code \[sup\]...\[/sup], which wraps the inner_text with <sup> tags
|
17
|
+
#
|
18
|
+
# module UBBParser
|
19
|
+
# def render_sup(inner_text, attributes = {}, parse_options = {})
|
20
|
+
# "<sup>{inner_text}</sup>"
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# When defining new ubb codes with a method and the name contains a dash, replace the dash by an underscore.
|
25
|
+
# I.e. the ubb code for img-left uses the method render_img_left
|
26
|
+
|
27
|
+
module UBBParser
|
28
|
+
|
29
|
+
# Converts a strings containing key-value-list into a hash. This function is mostly used by the parser itself.
|
30
|
+
# Attributes are given to the render methods as a hash.
|
31
|
+
def self.attrib_str_to_hash(attrib_str)
|
32
|
+
result = {:original_attrib_str => attrib_str.gsub(/^=/, "")}
|
33
|
+
|
34
|
+
attrib_str.insert(0, "default") if (attrib_str[0] == "=")
|
35
|
+
attrib_str.scan(/((\S*)=(\"[^\"]*\"|\'[^\']*\'|\S*))/) { | all, key, val |
|
36
|
+
result[(key.gsub(/-/, "_").to_sym rescue key)] = val.gsub(/^[\"\']/, "").gsub(/[\"\']$/, "")
|
37
|
+
}
|
38
|
+
return result
|
39
|
+
end
|
40
|
+
|
41
|
+
# Converts a hash into a string with key-values. You can use one of the following options:
|
42
|
+
# options[:allowed_keys]:: An array of keys that are only allowed
|
43
|
+
# options[:denied_keys]:: An array of keys that are denied
|
44
|
+
def self.hash_to_attrib_str(hash, options = {})
|
45
|
+
hash.delete_if { | k, v | !options[:allowed_keys].include?(k) } if options[:allowed_keys].is_a?(Array)
|
46
|
+
hash.delete_if { | k, v | options[:denied_keys].include?(k) } if options[:denied_keys].is_a?(Array)
|
47
|
+
return hash.map { | k, v | v = v.to_s.gsub(/\\|'/) { |c| "\\#{c}" }; "#{k}='#{v}'" }.join(" ");
|
48
|
+
end
|
49
|
+
|
50
|
+
# Parses the given text with ubb code into html. Use parse_options to specify a hash of options:
|
51
|
+
# parse_options\[:convert_newlines\]:: A boolean whether newlines should be convert into <br /> tags (default: true).
|
52
|
+
# parse_options\[:protect_email\]:: A boolean whether email addresses should be protected from spoofing using embedded JavaScript.
|
53
|
+
# parse_options\[:class_xxx\]:: A string with css class(es) that is embedded in the html for the tag xxx. Not all tags supports this.
|
54
|
+
# Replaces a dash in a tag with underscore (i.e. the class for img-left is defined in :class_img_left).
|
55
|
+
# {:class_code: "prettify linenums"} => <pre class='prettify linenums'>...</pre>
|
56
|
+
#
|
57
|
+
# When developing your own tags, you can also define your own parse_options.
|
58
|
+
def self.parse(text, parse_options = {})
|
59
|
+
result = ""
|
60
|
+
scnr = StringScanner.new(text)
|
61
|
+
parse_options.each { | k, v | v.to_s.gsub(/-/, "_").gsub(/[^\w]+/, "") if (k.to_s.start_with?("class_")); v }
|
62
|
+
while (!scnr.eos?)
|
63
|
+
untagged_text = scnr.scan(/[^\[]*/)
|
64
|
+
|
65
|
+
# convert newlines to breaks
|
66
|
+
untagged_text.gsub!(/\n/, "<br />") if (!parse_options.include?(:convert_newlines) || parse_options[:convert_newlines])
|
67
|
+
|
68
|
+
# check for untagged url's
|
69
|
+
uri_pattern = /(((http|https|ftp)\:\/\/)|(www))[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,4}(:[a-zA-Z0-9]*)?\/?([a-zA-Z0-9\-\._\?\,\'\/\\\+&%\$#\=~])*[^\.\,\)\(\s]*/
|
70
|
+
untagged_text.gsub!(uri_pattern) { | url, | render_url(url, {}, parse_options) }
|
71
|
+
|
72
|
+
# check for untagged emails
|
73
|
+
email_pattern = /(([a-zA-Z0-9_\-\.\+]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?))/
|
74
|
+
untagged_text.gsub!(email_pattern) { | email, | render_email(email, {}, parse_options) }
|
75
|
+
|
76
|
+
result << untagged_text
|
77
|
+
|
78
|
+
# check for the upcoming ubb tag and process it (if valid tag)
|
79
|
+
if (scnr.match?(/\[/))
|
80
|
+
scnr.skip(/\[/)
|
81
|
+
code = scnr.scan(/[\w-]*/)
|
82
|
+
method_name = ("render_" + code.to_s.gsub(/-/, "_")).to_sym
|
83
|
+
if ((scnr.eos?) || (code == "") || (!self.respond_to?(method_name)))
|
84
|
+
result << "[" + code
|
85
|
+
else
|
86
|
+
attributes = self.attrib_str_to_hash(scnr.scan(/[^\]]*/))
|
87
|
+
scnr.skip(/\]/)
|
88
|
+
inner_text = scnr.scan_until(/\[\/#{code}\]/)
|
89
|
+
if inner_text.nil? #no closing tag found
|
90
|
+
inner_text = scnr.rest
|
91
|
+
scnr.terminate
|
92
|
+
else
|
93
|
+
inner_text.chomp!("[/#{code}]")
|
94
|
+
end
|
95
|
+
method_result = self.send(method_name, inner_text, attributes, parse_options).to_s
|
96
|
+
result << method_result
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
return result
|
101
|
+
end
|
102
|
+
|
103
|
+
# Returns true if the given value matches the given regular expression.
|
104
|
+
# :category: Validation methods
|
105
|
+
def self.matches_regexp?(value, regexp)
|
106
|
+
return !value.to_s.match(regexp).nil?
|
107
|
+
end
|
108
|
+
|
109
|
+
# Returns true if the given value is a valid email address
|
110
|
+
# :category: Validation methods
|
111
|
+
def self.is_email?(value)
|
112
|
+
return false if !value.is_a?(String)
|
113
|
+
return self.matches_regexp?(value, /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Returns true if the given value is a valid url
|
117
|
+
# :category: Validation methods
|
118
|
+
def self.is_url?(value)
|
119
|
+
return self.matches_regexp?(value, /^(http|https)\:\/\/([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(\/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$/)
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
# Converts the [anchor=myname]...[/anchor] tag into <a name='myname'>...</a>. Use the :class_anchor parse option to define html classes.
|
125
|
+
# :category: Render methods
|
126
|
+
def self.render_anchor(inner_text, attributes = {}, parse_options = {})
|
127
|
+
name = attributes[:default] || ""
|
128
|
+
name.inner_text.gsub!(/\\|'/) { |c| "\\#{c}" }
|
129
|
+
"<a name='#{name}' class='#{parse_options[:class_anchor].to_s.strip}'>#{self.parse(inner_text, parse_options)}</a>"
|
130
|
+
end
|
131
|
+
|
132
|
+
# Converts the url in the inner_text into a webplayer, playing the audio file.
|
133
|
+
# :category: Render methods
|
134
|
+
def self.render_audio(inner_text, attributes = {}, parse_options = {})
|
135
|
+
# Not yet implemented
|
136
|
+
end
|
137
|
+
|
138
|
+
# Renders the inner_text bold (using <strong>).
|
139
|
+
# :category: Render methods
|
140
|
+
def self.render_b(inner_text, attributes = {}, parse_options = {})
|
141
|
+
"<strong>#{self.parse(inner_text, parse_options)}</strong>"
|
142
|
+
end
|
143
|
+
|
144
|
+
# Converts [br] into a <br />.
|
145
|
+
# :category: Render methods
|
146
|
+
def self.render_br(inner_text, attributes = {}, parse_options = {})
|
147
|
+
"<br />#{self.parse(inner_text, parse_options)}"
|
148
|
+
end
|
149
|
+
|
150
|
+
# Converts all lines in the inner_text as a bullet list. Each line represents one list item. Empty lines are ignored. Use the :class_bullet parse option to define html classes.
|
151
|
+
# :category: Render methods
|
152
|
+
def self.render_bullets(inner_text, attributes = {}, parse_options = {})
|
153
|
+
items = inner_text.split(/\n/)
|
154
|
+
items.delete_if { | item | item.strip == "" }
|
155
|
+
items.map! { | item | "<li>" + self.parse(item, parse_options) + "</li>" }
|
156
|
+
return (items.empty?) ? "" : "<ul class='#{parse_options[:class_bullets].to_s.strip}'>" + items.join("") + "</ul>"
|
157
|
+
end
|
158
|
+
|
159
|
+
# Centers the inner_text.
|
160
|
+
# :category: Render methods
|
161
|
+
def self.render_center(inner_text, attributes = {}, parse_options = {})
|
162
|
+
"<div style='text-align: center'>#{self.parse(inner_text, parse_options)}</div>"
|
163
|
+
end
|
164
|
+
|
165
|
+
# Assures the inner_text is rendered below floating elements.
|
166
|
+
# :category: Render methods
|
167
|
+
def self.render_clear(inner_text, attributes = {}, parse_options = {})
|
168
|
+
"<div style='clear: both'></div>"
|
169
|
+
end
|
170
|
+
|
171
|
+
# Changes the font color of the inner_text
|
172
|
+
# :category: Render methods
|
173
|
+
def self.render_color(inner_text, attributes = {}, parse_options = {})
|
174
|
+
"<div style='color:#{attributes[:default]}'>#{self.parse(inner_text, parse_options)}</div>"
|
175
|
+
end
|
176
|
+
|
177
|
+
# Ignores all the inner_text
|
178
|
+
# :category: Render methods
|
179
|
+
def self.render_comment(inner_text, attributes = {}, parse_options = {})
|
180
|
+
""
|
181
|
+
end
|
182
|
+
|
183
|
+
# Places the inner_text in a fixed font type. Also adds the classes prettify and linenums for styling purposes. Use the :class_code parse option to define html classes.
|
184
|
+
# :category: Render methods
|
185
|
+
def self.render_code(inner_text, attributes = {}, parse_options = {})
|
186
|
+
"<pre class='#{parse_options[:class_code].to_s.strip}'>#{inner_text}</pre>"
|
187
|
+
end
|
188
|
+
|
189
|
+
# Renders csv-data into a html table. You can use the following attributes:
|
190
|
+
# has_header: The first row should be rendered as header cells (using th).
|
191
|
+
# :category: Render methods
|
192
|
+
def self.render_csv(inner_text, attributes = {}, parse_options = {})
|
193
|
+
head_cells = body_cells = ""
|
194
|
+
cell_tag = (attributes[:has_header] || true) ? "th" : "td"
|
195
|
+
lines = inner_text.split(/\n/)
|
196
|
+
csv_pattern = /(\"[^\"]*\"|\'[^\']*\'|[^\n\r,]+)[,\n]?/
|
197
|
+
lines.each { | line |
|
198
|
+
cells = attrib_str.scan(csv_pattern) { | item | "<#{cell_tag}>#{item}</#{cell_tag}>" }
|
199
|
+
cells = "<tr>#{cells}</tr>"
|
200
|
+
if (cell_tag == "th")
|
201
|
+
head_cells += cells
|
202
|
+
else
|
203
|
+
body_cells += cells
|
204
|
+
end
|
205
|
+
cell_tag = "td"
|
206
|
+
}
|
207
|
+
result = ""
|
208
|
+
if (!head_cells.empty? || !body_cells.empty?)
|
209
|
+
result = "<table class='#{parse_options[:class_csv].to_s.strip}'>"
|
210
|
+
result += "<thead>#{head_cells}</thead>" if (!head_cells.empty?)
|
211
|
+
result += "<tbody>#{body_cells}</tbody>"
|
212
|
+
result = "</table>"
|
213
|
+
end
|
214
|
+
return result
|
215
|
+
end
|
216
|
+
|
217
|
+
# Renders an email address. There are two options to define:
|
218
|
+
# [email]info@osingasoftware.nl[/email]
|
219
|
+
# [email=info@osingasoftware.nl]Osinga Software[/email]
|
220
|
+
# By default the email address is protected against spoofing, using JavaScript. Use the :class_email parse option to define html classes.
|
221
|
+
# :category: Render methods
|
222
|
+
def self.render_email(inner_text, attributes = {}, parse_options = {})
|
223
|
+
email = (attributes[:default] || inner_text)
|
224
|
+
if (!self.is_email?(email))
|
225
|
+
parse_options[:class_email] = parse_options[:class_email].to_s + " ubbparser-error"
|
226
|
+
result = "<span class='#{parse_options[:class_email].to_s.strip}'>UBB error: invalid email address #{email}</span>"
|
227
|
+
elsif ((parse_options.has_key?(:protect_email) && !parse_options[:protect_email]) || (attributes[:protected] == "false"))
|
228
|
+
result = "<a href='mailto:#{email}' class='#{parse_options[:class_email].to_s.strip}'>#{inner_text}</a>"
|
229
|
+
else
|
230
|
+
username, domain = email.split("@", 2)
|
231
|
+
id = "ubb-email-" + SecureRandom.hex(16)
|
232
|
+
|
233
|
+
# Some generic javascript so every browser can parse this (instantly), regardless of used framework
|
234
|
+
title = (inner_text == email) ? "protected email address" : inner_text
|
235
|
+
script = "<script type='text/javascript'>obj=document.getElementById(\"#{id}\");email=obj.getAttribute(\"data-username\")+\"@\"+obj.getAttribute(\"data-domain\");obj.href=\"mailto:\"+email;obj.innerHTML=\"#{title}\"</script>";
|
236
|
+
result = "<a id='#{id}' class='#{parse_options[:class_email].to_s.strip}' href='#' data-username='#{username}' data-domain='#{domain}'>#{title}</a>#{script}"
|
237
|
+
end
|
238
|
+
return result
|
239
|
+
end
|
240
|
+
|
241
|
+
# Renders the inner_text in the specified list. The list should contain CSS style font-families, i.e.:
|
242
|
+
# [font=Arial, Helvetica, Sans]...[/font]
|
243
|
+
# :category: Render methods
|
244
|
+
def self.render_font(inner_text, attributes = {}, parse_options = {})
|
245
|
+
font = attributes[:original_attrib_str].gsub!(/\\|'/) { |c| "\\#{c}" }
|
246
|
+
"<span style='font-family: #{font}'>#{self.parse(inner_text, parse_options)}</span>"
|
247
|
+
end
|
248
|
+
|
249
|
+
# Renders the inner_text in a H1 heading.
|
250
|
+
# :category: Render methods
|
251
|
+
def self.render_h1(inner_text, attributes = {}, parse_options = {})
|
252
|
+
"<h1>#{self.parse(inner_text, parse_options)}</h1>"
|
253
|
+
end
|
254
|
+
|
255
|
+
# Renders the inner_text in a H2 heading.
|
256
|
+
# :category: Render methods
|
257
|
+
def self.render_h2(inner_text, attributes = {}, parse_options = {})
|
258
|
+
"<h2>#{self.parse(inner_text, parse_options)}</h2>"
|
259
|
+
end
|
260
|
+
|
261
|
+
# Renders the inner_text in a H3 heading.
|
262
|
+
# :category: Render methods
|
263
|
+
def self.render_h3(inner_text, attributes = {}, parse_options = {})
|
264
|
+
"<h3>#{self.parse(inner_text, parse_options)}</h3>"
|
265
|
+
end
|
266
|
+
|
267
|
+
# Renders a horizontal ruler.
|
268
|
+
# :category: Render methods
|
269
|
+
def self.render_hr(inner_text, attributes = {}, parse_options = {})
|
270
|
+
"<hr />#{self.parse(inner_text, parse_options)}"
|
271
|
+
end
|
272
|
+
|
273
|
+
# Renders the inner_text in italic.
|
274
|
+
# :category: Render methods
|
275
|
+
def self.render_i(inner_text, attributes = {}, parse_options = {})
|
276
|
+
"<em>#{self.parse(inner_text, parse_options)}</em>"
|
277
|
+
end
|
278
|
+
|
279
|
+
# Renders an iframe. Use the inner_text as source. Use the :class_iframe parse option to define html classes.
|
280
|
+
# :category: Render methods
|
281
|
+
def self.render_iframe(inner_text, attributes = {}, parse_options = {})
|
282
|
+
src = inner_text
|
283
|
+
src = "http://" + src if (src.match(/^www\./))
|
284
|
+
src.gsub!(/\\|'/) { |c| "\\#{c}" }
|
285
|
+
attributes[:src] = inner_text
|
286
|
+
attributes[:class] = (attributes[:class].to_s + " " + parse_options[:class_iframe].to_s).strip if ((!attributes.has_key?(:skip_class)) || !attributes[:skip_class])
|
287
|
+
attrib_str = self.hash_to_attrib_str(attributes, :allowed_keys => [:src, :class, :frameborder, :marginwidth, :marginheight, :width, :height])
|
288
|
+
return "<iframe #{attrib_str}></iframe>"
|
289
|
+
end
|
290
|
+
|
291
|
+
# Doesn't render the ubb code in the inner_text. It does strip all html-tags from the inner_text
|
292
|
+
# :category: Render methods
|
293
|
+
def self.render_ignore(inner_text, attributes = {}, parse_options = {})
|
294
|
+
inner_text
|
295
|
+
end
|
296
|
+
|
297
|
+
# Renders an image. Use the :class_img parse option to define html classes.
|
298
|
+
# :category: Render methods
|
299
|
+
def self.render_img(inner_text, attributes = {}, parse_options = {})
|
300
|
+
url = inner_text
|
301
|
+
url = "" if (!self.is_url?(inner_text))
|
302
|
+
attributes[:src] = inner_text.gsub(/\\|'/) { |c| "\\#{c}" }
|
303
|
+
attributes[:alt] ||= ""
|
304
|
+
attributes[:class] = parse_options[:class_img] if ((!attributes.has_key?(:skip_class)) || !attributes[:skip_class])
|
305
|
+
attrib_str = self.hash_to_attrib_str(attributes, :allowed_keys => [:src, :alt, :styles, :class])
|
306
|
+
return "<img #{attrib_str} />"
|
307
|
+
end
|
308
|
+
|
309
|
+
# Renders an image, floated on the left side of the text frame. Use the :class_img_left parse option to define html classes.
|
310
|
+
# :category: Render methods
|
311
|
+
def self.render_img_left(inner_text, attributes = {}, parse_options = {})
|
312
|
+
attributes[:styles] = "float: left; margin: 0px 10px 10px 0px"
|
313
|
+
attributes[:class] += " " + parse_options[:class_img_left]
|
314
|
+
attributes[:skip_class] = true
|
315
|
+
render_img(inner_text, attributes, parse_options)
|
316
|
+
end
|
317
|
+
|
318
|
+
# Renders an image, floated on the right side of the text frame. Use the :class_img_right parse option to define html classes.
|
319
|
+
# :category: Render methods
|
320
|
+
def self.render_img_right(inner_text, attributes = {}, parse_options = {})
|
321
|
+
attributes[:styles] = "float: left; margin: 0px 0px 10px 10px"
|
322
|
+
attributes[:class] += " " + parse_options[:class_img_right]
|
323
|
+
attributes[:skip_class] = true
|
324
|
+
render_img(inner_text, attributes, parse_options)
|
325
|
+
end
|
326
|
+
|
327
|
+
# Renders the inner_text with a justified text alignment.
|
328
|
+
# :category: Render methods
|
329
|
+
def self.render_justify(inner_text, attributes = {}, parse_options = {})
|
330
|
+
"<div style='text-align: justify'>#{self.parse(inner_text, parse_options)}</div>"
|
331
|
+
end
|
332
|
+
|
333
|
+
# Renders the inner_text with a left text alignment.
|
334
|
+
# :category: Render methods
|
335
|
+
def self.render_left(inner_text, attributes = {}, parse_options = {})
|
336
|
+
"<div style='text-align: left'>#{self.parse(inner_text, parse_options)}</div>"
|
337
|
+
end
|
338
|
+
|
339
|
+
# Renders the inner_text as an ordered list. Each line represents a list item. Use the :class_list parse option to define html classes.
|
340
|
+
# :category: Render methods
|
341
|
+
def self.render_list(inner_text, attributes = {}, parse_options = {})
|
342
|
+
items = inner_text.split(/\n/)
|
343
|
+
items.delete_if { | item | item.strip == "" }
|
344
|
+
items.map! { | item | "<li>" + self.parse(item, parse_options) + "</li>" }
|
345
|
+
return (items.empty?) ? "" : "<ul class='#{parse_options[:class_list].to_s.strip}'>" + items.join("") + "</ol>"
|
346
|
+
end
|
347
|
+
|
348
|
+
# Renders the inner_text as a paragraph. Use the :class_p parse option to define html classes.
|
349
|
+
# :category: Render methods
|
350
|
+
def self.render_p(inner_text, attributes = {}, parse_options = {})
|
351
|
+
"<p class='#{parse_options[:class_p].to_s.strip}'>#{self.parse(inner_text, parse_options)}</p>"
|
352
|
+
end
|
353
|
+
|
354
|
+
# Renders the inner_text with a right text alignment.
|
355
|
+
# :category: Render methods
|
356
|
+
def self.render_right(inner_text, attributes = {}, parse_options = {})
|
357
|
+
"<div style='text-align: right'>#{self.parse(inner_text, parse_options)}</div>"
|
358
|
+
end
|
359
|
+
|
360
|
+
# Renders the inner_text in a <div> block with inline CSS styles, i.e.:
|
361
|
+
# [style color: red; border: 1px solid green]...[/style]
|
362
|
+
# :category: Render methods
|
363
|
+
def self.render_style(inner_text, attributes = {}, parse_options = {})
|
364
|
+
styles = attributes[:original_attrib_str].gsub(/'/, "\'")
|
365
|
+
"<div style='#{styles}'>#{self.parse(inner_text, parse_options)}</div>"
|
366
|
+
end
|
367
|
+
|
368
|
+
# Converts the [table] to a <table>. Always use this in combination with [tr] and [td] or [th]. Use the :class_table parse option to define html classes.
|
369
|
+
# [style color: red; border: 1px solid green]...[/style]
|
370
|
+
# :category: Render methods
|
371
|
+
def self.render_table(inner_text, attributes = {}, parse_options = {})
|
372
|
+
styles = attributes[:default].gsub(/'/, "\'")
|
373
|
+
"<div style='#{styles}' class='#{parse_options[:class_table].to_s.strip}'>#{self.parse(inner_text, parse_options)}</div>"
|
374
|
+
end
|
375
|
+
|
376
|
+
# Renders the inner_text underline. Use this with caution, since underline text is associated with hyperlinks.
|
377
|
+
# :category: Render methods
|
378
|
+
def self.render_u(inner_text, attributes = {}, parse_options = {})
|
379
|
+
"<u>#{self.parse(inner_text, parse_options)}</u>"
|
380
|
+
end
|
381
|
+
|
382
|
+
# Renders a web addres. There are two options to define:
|
383
|
+
# [url]www.osingasoftware.nl[/ur]
|
384
|
+
# [url=www.osingasoftware.nl]Osinga Software[/url]
|
385
|
+
# Use the :class_url parse option to define html classes.
|
386
|
+
# :category: Render methods
|
387
|
+
def self.render_url(inner_text, attributes = {}, parse_options = {})
|
388
|
+
url = (attributes[:default] || inner_text)
|
389
|
+
url = "http://" + url if (url.match(/^www\./))
|
390
|
+
url.gsub!(/\\|'/) { |c| "\\#{c}" }
|
391
|
+
return "<a href='#{url}' class='#{parse_options[:class_url].to_s.strip}'>#{inner_text}</a>"
|
392
|
+
end
|
393
|
+
|
394
|
+
# Renders a YouTube video using the video id or url in the inner_text.
|
395
|
+
# :category: Render methods
|
396
|
+
def self.render_vimeo(inner_text, attributes = {}, parse_options = {})
|
397
|
+
attributes[:width] ||= 500
|
398
|
+
attributes[:height] ||= 281
|
399
|
+
attributes[:class] = parse_options[:class_vimeo]
|
400
|
+
attributes[:skip_class] = true
|
401
|
+
videoid = (inner_text.scan(/[0-9]{5,}/).to_a)[0].to_s
|
402
|
+
src = "http://player.vimeo.com/video/#{videoid}"
|
403
|
+
return render_iframe(src, attributes, parse_options)
|
404
|
+
end
|
405
|
+
|
406
|
+
# Renders a YouTube video using the video id or url in the inner_text.
|
407
|
+
# :category: Render methods
|
408
|
+
def self.render_youtube(inner_text, attributes = {}, parse_options = {})
|
409
|
+
attributes[:width] ||= 560
|
410
|
+
attributes[:height] ||= 315
|
411
|
+
attributes[:class] = parse_options[:class_youtube]
|
412
|
+
attributes[:skip_class] = true
|
413
|
+
videoid = !inner_text.match(/^[^\?\&]$/).nil? ? inner_text : inner_text.scan(/(\?|&)v=([^\&]*)/)[0][1]
|
414
|
+
src = "http://www.youtube.com/embed/#{videoid}"
|
415
|
+
return render_iframe(src, attributes, parse_options)
|
416
|
+
end
|
417
|
+
|
418
|
+
# Renders a Youtube, Vimeo or Zideo video using the video id or url in the inner_text.
|
419
|
+
# It automatically determines which video renderer should be used based on the given url.
|
420
|
+
# :category: Render methods
|
421
|
+
def self.render_video(inner_text, attributes = {}, parse_options = {})
|
422
|
+
attributes[:class] += " " + parse_options[:class_zideo]
|
423
|
+
url = inner_text
|
424
|
+
if (!url.match(/zideo\.nl/).nil?)
|
425
|
+
return self.render_zideo(inner_text, attributes, parse_options)
|
426
|
+
elsif (!url.match(/[0-9]{5,}/).nil?) || (!url.match(/vimeo/).nil?)
|
427
|
+
return self.render_vimeo(inner_text, attributes, parse_options)
|
428
|
+
elsif (!url.match(/youtu/).nil?) || (!url.match(/^[^\?\&]+{11}$/).nil?)
|
429
|
+
return self.render_youtube(inner_text, attributes, parse_options)
|
430
|
+
else
|
431
|
+
return "Unknown video"
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
# Renders a zideo.nl video using the video id or url in the inner_text.
|
436
|
+
# :category: Render methods
|
437
|
+
def self.render_zideo(inner_text, attributes = {}, parse_options = {})
|
438
|
+
attributes[:width] ||= 480
|
439
|
+
attributes[:height] ||= 360
|
440
|
+
attributes[:class] += " " + parse_options[:class_zideo]
|
441
|
+
attributes[:skip_class] = true
|
442
|
+
videoid = !inner_text.match(/^\w+$/).nil? ? inner_text : (inner_text.scan(/playzideo\/(\w+)/).to_a)[1].to_s
|
443
|
+
src = "http://www.zideo.nl/zideomediaplayer.php?" + inner_text
|
444
|
+
return render_iframe(src, attributes, parse_options)
|
445
|
+
end
|
446
|
+
|
447
|
+
end
|
metadata
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ubbparser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.5
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Taco Jan Osinga
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-16 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A simple and flexibel ubb parser.
|
15
|
+
email: info@osingasoftware.nl
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/ubbparser.rb
|
21
|
+
homepage: http://ubbparser.mojura.nl
|
22
|
+
licenses: []
|
23
|
+
post_install_message:
|
24
|
+
rdoc_options: []
|
25
|
+
require_paths:
|
26
|
+
- lib
|
27
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
requirements: []
|
40
|
+
rubyforge_project:
|
41
|
+
rubygems_version: 1.8.11
|
42
|
+
signing_key:
|
43
|
+
specification_version: 3
|
44
|
+
summary: UBB Parser
|
45
|
+
test_files: []
|