rubb 0.9.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.
- data/.gitignore +5 -0
- data/LICENSE +19 -0
- data/README.rdoc +37 -0
- data/Rakefile +28 -0
- data/VERSION +1 -0
- data/init.rb +1 -0
- data/lib/rubb.rb +22 -0
- data/lib/rubb/node.rb +25 -0
- data/lib/rubb/node/image.rb +25 -0
- data/lib/rubb/node/quote.rb +22 -0
- data/lib/rubb/node/simple.rb +21 -0
- data/lib/rubb/node/styled.rb +28 -0
- data/lib/rubb/node/text.rb +22 -0
- data/lib/rubb/node/url.rb +26 -0
- data/lib/rubb/parser.rb +128 -0
- data/test/test_helper.rb +2 -0
- data/test/test_rubb.rb +187 -0
- metadata +82 -0
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2010 Peter Jihoon Kim
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
= RuBB
|
2
|
+
|
3
|
+
BBCode Parser for Ruby.
|
4
|
+
|
5
|
+
RuBB parses BBCode by generating a parse tree, so it is able to handle nested BBCode tags properly.
|
6
|
+
|
7
|
+
== Usage
|
8
|
+
|
9
|
+
RuBB.to_html('[b]hello[/b]')
|
10
|
+
|
11
|
+
'[b]hello[/b]'.to_html
|
12
|
+
|
13
|
+
== BBCode Tags
|
14
|
+
|
15
|
+
RuBB supports the following BBCode tags:
|
16
|
+
|
17
|
+
[b]text[/b]
|
18
|
+
[i]text[/i]
|
19
|
+
[u]text[/u]
|
20
|
+
[s]text[/s]
|
21
|
+
[size=10]text[/size]
|
22
|
+
[color=#ff0000]text[/color]
|
23
|
+
[center]text[/center]
|
24
|
+
[quote]text[/quote]
|
25
|
+
[quote=someone]text[/quote]
|
26
|
+
[url]http://github.com/petejkim/rubb/[/url]
|
27
|
+
[url=http://github.com/petejkim/rubb/]RuBB[/url]
|
28
|
+
[img]http://test.com/test.jpg[/img]
|
29
|
+
[img=640x480]http://test.com/test.jpg[/img]
|
30
|
+
[ul][li]text[/li][/ul]
|
31
|
+
[ol][li]text[/li][/ol]
|
32
|
+
[code]text[/code]
|
33
|
+
[table][tr][th]text[/th][/tr][tr][td]text[/td][/tr][/table]
|
34
|
+
|
35
|
+
== Copyright
|
36
|
+
|
37
|
+
Copyright (c) 2010 Peter Jihoon Kim. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
|
7
|
+
Jeweler::Tasks.new do |s|
|
8
|
+
s.name = "rubb"
|
9
|
+
s.summary = "BBCode Parser for Ruby that supports nested BBCode tags."
|
10
|
+
s.description = s.summary
|
11
|
+
s.homepage = "http://github.com/petejkim/rubb"
|
12
|
+
s.authors = ["Peter Jihoon Kim"]
|
13
|
+
s.email = "raingrove@gmail.com"
|
14
|
+
end
|
15
|
+
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler - or one of its dependencies - is not available. " <<
|
19
|
+
"Install it with: sudo gem install jeweler -s http://gemcutter.org"
|
20
|
+
end
|
21
|
+
|
22
|
+
Rake::TestTask.new do |t|
|
23
|
+
t.libs << 'lib'
|
24
|
+
t.pattern = 'test/**/test_*.rb'
|
25
|
+
t.verbose = true
|
26
|
+
end
|
27
|
+
|
28
|
+
task :default => :test
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.9.0
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'rubb'
|
data/lib/rubb.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module RuBB
|
2
|
+
class << self
|
3
|
+
def parse(bbcode)
|
4
|
+
Parser.parse(Parser.escape_html(bbcode), nil)
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_html(bbcode)
|
8
|
+
parse(bbcode).to_html
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class String
|
14
|
+
def bb_to_html
|
15
|
+
RuBB.to_html(self)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
$: << (File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
20
|
+
|
21
|
+
require 'rubb/node'
|
22
|
+
require 'rubb/parser'
|
data/lib/rubb/node.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module RuBB
|
2
|
+
class Node
|
3
|
+
attr_accessor :children
|
4
|
+
attr_accessor :leftover
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
@children = options[:children] || []
|
8
|
+
@leftover = options[:leftover]
|
9
|
+
end
|
10
|
+
|
11
|
+
def <<(child)
|
12
|
+
@children << child
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_html
|
16
|
+
html = ''
|
17
|
+
@children.each do |child|
|
18
|
+
html += child ? child.to_html : ''
|
19
|
+
end
|
20
|
+
html
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'node/*.rb')).each {|f| require f }
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RuBB
|
2
|
+
class Node
|
3
|
+
class Image < Node
|
4
|
+
attr_accessor :width
|
5
|
+
attr_accessor :height
|
6
|
+
|
7
|
+
def initialize(options={})
|
8
|
+
super(options)
|
9
|
+
@width = options[:width]
|
10
|
+
@height = options[:height]
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_html
|
14
|
+
if(@width && @height)
|
15
|
+
url = Parser.escape_quotes(@children.map {|c| c ? c.to_html : '' }.join)
|
16
|
+
html = "<img src=\"#{url}\" style=\"width: #{@width}px; height: #{@height}px;\" alt=\"\" />"
|
17
|
+
else
|
18
|
+
url = Parser.escape_quotes(@children.map {|c| c ? c.to_html : '' }.join)
|
19
|
+
html = "<img src=\"#{url}\" alt=\"\" />"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module RuBB
|
2
|
+
class Node
|
3
|
+
class Quote < Node
|
4
|
+
attr_accessor :who
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
super(options)
|
8
|
+
@who = options[:who] || ''
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_html
|
12
|
+
html = '<p class="rubb_quote_header">Quote:</p><blockquote>'
|
13
|
+
html += "<p class=\"rubb_quote_who\">Originally Posted by <strong>#{Parser.escape_quotes(@who)}</strong></p>" unless(@who.empty?)
|
14
|
+
html += '<p class="rubb_quote_content">'
|
15
|
+
@children.each do |child|
|
16
|
+
html += child ? child.to_html : ''
|
17
|
+
end
|
18
|
+
html + '</p></blockquote>'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RuBB
|
2
|
+
class Node
|
3
|
+
class Simple < Node
|
4
|
+
attr_accessor :html_tag_name
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
super(options)
|
8
|
+
@html_tag_name = options[:html_tag_name] || ''
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_html
|
12
|
+
html = "<#{@html_tag_name}>"
|
13
|
+
@children.each do |child|
|
14
|
+
html += child ? child.to_html : ''
|
15
|
+
end
|
16
|
+
html + "</#{@html_tag_name}>"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module RuBB
|
2
|
+
class Node
|
3
|
+
class Styled < Node
|
4
|
+
attr_accessor :style_hash
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
super(options)
|
8
|
+
@style_hash = options[:style_hash] || {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_html
|
12
|
+
html = '<span style="'
|
13
|
+
@style_hash.each do |k,v|
|
14
|
+
if(v) # if v is not nil
|
15
|
+
v = v[/\A([^;]*);/,1] if v.include?(';') # ignore semicolons and any trailing text
|
16
|
+
html += "#{k}: #{v};"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
html += '">'
|
20
|
+
@children.each do |child|
|
21
|
+
html += child ? child.to_html : ''
|
22
|
+
end
|
23
|
+
html + "</span>"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module RuBB
|
2
|
+
class Node
|
3
|
+
class Text < Node
|
4
|
+
attr_accessor :text
|
5
|
+
attr_accessor :ignore_whitespace
|
6
|
+
|
7
|
+
def initialize(options={})
|
8
|
+
super(options)
|
9
|
+
@text = options[:text] || ''
|
10
|
+
@ignore_whitespace = options[:ignore_whitespace] || false
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_html
|
14
|
+
if(@ignore_whitespace)
|
15
|
+
@text.gsub(/\s/, '')
|
16
|
+
else
|
17
|
+
@text.gsub(/\r\n?/, "\n").gsub(/\n/, '<br />')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module RuBB
|
2
|
+
class Node
|
3
|
+
class URL < Node
|
4
|
+
attr_accessor :url
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
super(options)
|
8
|
+
@url = options[:url] || ''
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_html
|
12
|
+
unless(@url.empty?)
|
13
|
+
html = "<a href=\"#{Parser.escape_quotes(@url)}\">"
|
14
|
+
@children.each do |child|
|
15
|
+
html += child ? child.to_html : ''
|
16
|
+
end
|
17
|
+
html + '</a>'
|
18
|
+
else
|
19
|
+
url = Parser.escape_quotes(@children.map {|c| c ? c.to_html : '' }.join)
|
20
|
+
html = "<a href=\"#{url}\">#{url}</a>"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
data/lib/rubb/parser.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
module RuBB
|
2
|
+
class Parser
|
3
|
+
TEXT_REGEXP = /\A([^\[]+)/
|
4
|
+
BB_REGEXP = /\A\[([^\]]*)\]/
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def escape_html(code)
|
8
|
+
code.gsub(/&/,'&').gsub(/</,'<').gsub(/>/,'>')
|
9
|
+
end
|
10
|
+
|
11
|
+
def escape_quotes(code)
|
12
|
+
code.gsub(/"/, "\\\"").gsub(/'/, "\\\\'")
|
13
|
+
end
|
14
|
+
|
15
|
+
def remove_wrapping_quotes(code)
|
16
|
+
if code[0] == "\"" && code[code.length-1] == "\""
|
17
|
+
return code[/\A"(.*)"\z/,1]
|
18
|
+
elsif code[0] == "\'" && code[code.length-1] == "\'"
|
19
|
+
return code[/\A'(.*)'\z/,1]
|
20
|
+
end
|
21
|
+
code
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse(code, current_tag_name, extra_params={})
|
25
|
+
return nil if code.length == 0
|
26
|
+
|
27
|
+
ignore_bbcode_in_children = false
|
28
|
+
|
29
|
+
node = case current_tag_name
|
30
|
+
when 'b'
|
31
|
+
Node::Simple.new(:html_tag_name => 'strong')
|
32
|
+
when 'i'
|
33
|
+
Node::Simple.new(:html_tag_name => 'em')
|
34
|
+
when 'u'
|
35
|
+
Node::Simple.new(:html_tag_name => 'ins')
|
36
|
+
when 's'
|
37
|
+
Node::Simple.new(:html_tag_name => 'del')
|
38
|
+
when 'code'
|
39
|
+
ignore_bbcode_in_children = true
|
40
|
+
Node::Simple.new(:html_tag_name => 'pre')
|
41
|
+
when 'ul', 'ol', 'li', 'table', 'tr', 'th', 'td'
|
42
|
+
Node::Simple.new(:html_tag_name => current_tag_name)
|
43
|
+
when 'size'
|
44
|
+
Node::Styled.new(:style_hash => {'font-size' => (extra_params[:param] ? extra_params[:param].to_f.to_s + 'px' : nil)})
|
45
|
+
when 'color'
|
46
|
+
Node::Styled.new(:style_hash => {'color' => (extra_params[:param] || nil)})
|
47
|
+
when 'center'
|
48
|
+
Node::Styled.new(:style_hash => {'text-align' => 'center'})
|
49
|
+
when 'quote'
|
50
|
+
Node::Quote.new(:who => (extra_params[:param] || ''))
|
51
|
+
when 'url'
|
52
|
+
ignore_bbcode_in_children = true if extra_params[:param].nil?
|
53
|
+
Node::URL.new(:url => (extra_params[:param] || ''))
|
54
|
+
when 'img'
|
55
|
+
ignore_bbcode_in_children = true
|
56
|
+
if(extra_params[:param] && (dimensions = extra_params[:param].split('x')).size >= 2)
|
57
|
+
Node::Image.new(:width => dimensions[0].to_i, :height => dimensions[1].to_i)
|
58
|
+
else
|
59
|
+
Node::Image.new
|
60
|
+
end
|
61
|
+
else
|
62
|
+
Node.new
|
63
|
+
end
|
64
|
+
|
65
|
+
until code.empty?
|
66
|
+
match_data = code.match(TEXT_REGEXP)
|
67
|
+
|
68
|
+
if(match_data)
|
69
|
+
code.replace(match_data.post_match)
|
70
|
+
case current_tag_name
|
71
|
+
when 'ul', 'ol', 'table', 'tr' # ignore orphaned text within these tags
|
72
|
+
# do nothing
|
73
|
+
else
|
74
|
+
node << Node::Text.new(:text => match_data[1], :ignore_whitespace => ignore_bbcode_in_children)
|
75
|
+
end
|
76
|
+
else
|
77
|
+
match_data = code.match(BB_REGEXP)
|
78
|
+
if(match_data)
|
79
|
+
tag = match_data[1].sub(/\s*=\s*/,' = ').split(' ')
|
80
|
+
tag_name = tag.first.downcase
|
81
|
+
|
82
|
+
code.replace(match_data.post_match)
|
83
|
+
if(current_tag_name && tag_name == ('/' + current_tag_name))
|
84
|
+
return node
|
85
|
+
else
|
86
|
+
case current_tag_name
|
87
|
+
when 'ul', 'ol' # if current tag is a list tag, expect only li tag
|
88
|
+
if(tag_name == 'li')
|
89
|
+
node << parse(code, tag_name)
|
90
|
+
end
|
91
|
+
when 'table'
|
92
|
+
if(tag_name == 'tr')
|
93
|
+
node << parse(code, tag_name)
|
94
|
+
end
|
95
|
+
when 'tr'
|
96
|
+
if(tag_name == 'th' || tag_name == 'td')
|
97
|
+
node << parse(code, tag_name)
|
98
|
+
end
|
99
|
+
else # if current tag is not a list tag
|
100
|
+
if(ignore_bbcode_in_children)
|
101
|
+
node << Node::Text.new(:text => match_data[0], :ignore_whitespace => true)
|
102
|
+
else
|
103
|
+
case tag_name
|
104
|
+
when 'b', 'i', 'u', 's', 'code', 'center', 'ul', 'ol', 'table'
|
105
|
+
node << parse(code, tag_name)
|
106
|
+
when 'url', 'img', 'size', 'color', 'quote'
|
107
|
+
if(tag[1] == '=' && tag.size > 2) # param is present
|
108
|
+
param = remove_wrapping_quotes(tag[2..(tag.size)].join(' '))
|
109
|
+
node << parse(code, tag_name, {:param => param})
|
110
|
+
else
|
111
|
+
node << parse(code, tag_name)
|
112
|
+
end
|
113
|
+
else
|
114
|
+
node << Node::Text.new(:text => match_data[0])
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
node
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'parser/*.rb')).each {|f| require f }
|
data/test/test_helper.rb
ADDED
data/test/test_rubb.rb
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
$: << (File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
class RuBBTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_escape
|
9
|
+
bb = "<p>tom & jerry kids</p>"
|
10
|
+
html = "<p>tom & jerry kids</p>"
|
11
|
+
assert_equal html, bb.bb_to_html
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_text
|
15
|
+
bb = "hello\nbye"
|
16
|
+
html = "hello<br />bye"
|
17
|
+
assert_equal html, bb.bb_to_html
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_b
|
21
|
+
bb = '[b]hello[/b]'
|
22
|
+
html = '<strong>hello</strong>'
|
23
|
+
assert_equal html, bb.bb_to_html
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_i
|
27
|
+
bb = '[i]hello[/i]'
|
28
|
+
html = '<em>hello</em>'
|
29
|
+
assert_equal html, bb.bb_to_html
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_u
|
33
|
+
bb = '[u]hello[/u]'
|
34
|
+
html = '<ins>hello</ins>'
|
35
|
+
assert_equal html, bb.bb_to_html
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_s
|
39
|
+
bb = '[s]hello[/s]'
|
40
|
+
html = '<del>hello</del>'
|
41
|
+
assert_equal html, bb.bb_to_html
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_code
|
45
|
+
bb = '[code]<p>hi</p>[b]hi[/b][/code]'
|
46
|
+
html = '<pre><p>hi</p>[b]hi[/b]</pre>'
|
47
|
+
assert_equal html, bb.bb_to_html
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_center
|
51
|
+
bb = '[center]hello[/center]'
|
52
|
+
html = '<span style="text-align: center;">hello</span>'
|
53
|
+
assert_equal html, bb.bb_to_html
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_quote
|
57
|
+
bb = '[quote]hello world![/quote]'
|
58
|
+
html = '<p class="rubb_quote_header">Quote:</p><blockquote><p class="rubb_quote_content">hello world!</p></blockquote>'
|
59
|
+
assert_equal html, bb.bb_to_html
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_named_quote
|
63
|
+
bb = '[quote=raingrove]hello world![/quote]'
|
64
|
+
html = '<p class="rubb_quote_header">Quote:</p><blockquote><p class="rubb_quote_who">Originally Posted by <strong>raingrove</strong></p><p class="rubb_quote_content">hello world!</p></blockquote>'
|
65
|
+
assert_equal html, bb.bb_to_html
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_size
|
69
|
+
bb = '[size=16]hello[/size]'
|
70
|
+
html = '<span style="font-size: 16.0px;">hello</span>'
|
71
|
+
assert_equal html, bb.bb_to_html
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_semicolon
|
75
|
+
bb = '[size=16;display: none;]hello[/size]'
|
76
|
+
html = '<span style="font-size: 16.0px;">hello</span>'
|
77
|
+
assert_equal html, bb.bb_to_html
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_color
|
81
|
+
bb = '[color=#ff0000]hello[/color]'
|
82
|
+
html = '<span style="color: #ff0000;">hello</span>'
|
83
|
+
assert_equal html, bb.bb_to_html
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_url_simple
|
87
|
+
bb = '[url]http://test.com/[/url]'
|
88
|
+
html = '<a href="http://test.com/">http://test.com/</a>'
|
89
|
+
assert_equal html, bb.bb_to_html
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_url_named
|
93
|
+
bb = '[url=http://test.com/]Test[/url]'
|
94
|
+
html = '<a href="http://test.com/">Test</a>'
|
95
|
+
assert_equal html, bb.bb_to_html
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_url_named_with_single_quotes
|
99
|
+
bb = "[url=\'http://test.com/\']Test[/url]"
|
100
|
+
html = '<a href="http://test.com/">Test</a>'
|
101
|
+
assert_equal html, bb.bb_to_html
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_url_named_with_double_quotes
|
105
|
+
bb = '[url="http://test.com/"]Test[/url]'
|
106
|
+
html = '<a href="http://test.com/">Test</a>'
|
107
|
+
assert_equal html, bb.bb_to_html
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_escape_quotes
|
111
|
+
bb = "[url=hello\">hello<p class='test'>hi</p><a href=\"]hello[/url]"
|
112
|
+
html = "<a href=\"hello\\\">hello<p class=\\\'test\\\'>hi</p><a href=\\\"\">hello</a>"
|
113
|
+
assert_equal html, bb.bb_to_html
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_img_simple
|
117
|
+
bb = '[img]http://test.com/hello.jpg[/img]'
|
118
|
+
html = '<img src="http://test.com/hello.jpg" alt="" />'
|
119
|
+
assert_equal html, bb.bb_to_html
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_img_with_dimensions
|
123
|
+
bb = '[img=100x200]http://test.com/hello.jpg[/img]'
|
124
|
+
html = '<img src="http://test.com/hello.jpg" style="width: 100px; height: 200px;" alt="" />'
|
125
|
+
assert_equal html, bb.bb_to_html
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_img_with_dimensions_with_quotes
|
129
|
+
bb = '[img="100x200"]http://test.com/hello.jpg[/img]'
|
130
|
+
html = '<img src="http://test.com/hello.jpg" style="width: 100px; height: 200px;" alt="" />'
|
131
|
+
assert_equal html, bb.bb_to_html
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_img_with_invalid_dimensions
|
135
|
+
bb = '[img="100"]http://test.com/hello.jpg[/img]'
|
136
|
+
html = '<img src="http://test.com/hello.jpg" alt="" />'
|
137
|
+
assert_equal html, bb.bb_to_html
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_ul
|
141
|
+
bb = '[ul][li]item1[/li][li]item2[/li][/ul]'
|
142
|
+
html = '<ul><li>item1</li><li>item2</li></ul>'
|
143
|
+
assert_equal html, bb.bb_to_html
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_ol
|
147
|
+
bb = '[ol][li]item1[/li][li]item2[/li][/ol]'
|
148
|
+
html = '<ol><li>item1</li><li>item2</li></ol>'
|
149
|
+
assert_equal html, bb.bb_to_html
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_list_with_extraneous_stuff
|
153
|
+
bb = '[ul]blah[li]item1[/li][li]item2[/li]blah[b]blah[/b]blah[/ul]'
|
154
|
+
html = '<ul><li>item1</li><li>item2</li></ul>'
|
155
|
+
assert_equal html, bb.bb_to_html
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_table
|
159
|
+
bb = '[table][tr][th]col1[/th][th]col2[/th][/tr][tr][td]data1[/td][td]data2[/td][/tr][/table]'
|
160
|
+
html = '<table><tr><th>col1</th><th>col2</th></tr><tr><td>data1</td><td>data2</td></tr></table>'
|
161
|
+
assert_equal html, bb.bb_to_html
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_table_with_extraneous_stuff
|
165
|
+
bb = '[table]blah[tr]blah[th]col1[/th]blah[th]col2[/th]blah[/tr]blah[tr]blah[td]data1[/td]blah[td]data2[/td]blah[/tr]blah[/table]'
|
166
|
+
html = '<table><tr><th>col1</th><th>col2</th></tr><tr><td>data1</td><td>data2</td></tr></table>'
|
167
|
+
assert_equal html, bb.bb_to_html
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_str_around
|
171
|
+
bb = 'aaa[b]bbb[/b]ccc'
|
172
|
+
html = 'aaa<strong>bbb</strong>ccc'
|
173
|
+
assert_equal html, bb.bb_to_html
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_nested
|
177
|
+
bb = '[b]aaa[b]bbb[/b]ccc[/b]'
|
178
|
+
html = '<strong>aaa<strong>bbb</strong>ccc</strong>'
|
179
|
+
assert_equal html, bb.bb_to_html
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_complex
|
183
|
+
bb = "xx[s]aaa[b]bbb[u]eee[/u]ff\nff[/b]ccc[i]ggg[/i]hhh[/s]yy"
|
184
|
+
html = 'xx<del>aaa<strong>bbb<ins>eee</ins>ff<br />ff</strong>ccc<em>ggg</em>hhh</del>yy'
|
185
|
+
assert_equal html, bb.bb_to_html
|
186
|
+
end
|
187
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 9
|
8
|
+
- 0
|
9
|
+
version: 0.9.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Peter Jihoon Kim
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-07-12 00:00:00 +09:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: BBCode Parser for Ruby that supports nested BBCode tags.
|
22
|
+
email: raingrove@gmail.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- LICENSE
|
29
|
+
- README.rdoc
|
30
|
+
files:
|
31
|
+
- .gitignore
|
32
|
+
- LICENSE
|
33
|
+
- README.rdoc
|
34
|
+
- Rakefile
|
35
|
+
- VERSION
|
36
|
+
- init.rb
|
37
|
+
- lib/rubb.rb
|
38
|
+
- lib/rubb/node.rb
|
39
|
+
- lib/rubb/node/image.rb
|
40
|
+
- lib/rubb/node/quote.rb
|
41
|
+
- lib/rubb/node/simple.rb
|
42
|
+
- lib/rubb/node/styled.rb
|
43
|
+
- lib/rubb/node/text.rb
|
44
|
+
- lib/rubb/node/url.rb
|
45
|
+
- lib/rubb/parser.rb
|
46
|
+
- test/test_helper.rb
|
47
|
+
- test/test_rubb.rb
|
48
|
+
has_rdoc: true
|
49
|
+
homepage: http://github.com/petejkim/rubb
|
50
|
+
licenses: []
|
51
|
+
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options:
|
54
|
+
- --charset=UTF-8
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.3.7
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: BBCode Parser for Ruby that supports nested BBCode tags.
|
80
|
+
test_files:
|
81
|
+
- test/test_helper.rb
|
82
|
+
- test/test_rubb.rb
|