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 ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ pkg
5
+ doc
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
+
@@ -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(/&/,'&amp;').gsub(/</,'&lt;').gsub(/>/,'&gt;')
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 }
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require 'rubb'
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 = "&lt;p&gt;tom &amp; jerry kids&lt;/p&gt;"
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>&lt;p&gt;hi&lt;/p&gt;[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\\\"&gt;hello&lt;p class=\\\'test\\\'&gt;hi&lt;/p&gt;&lt;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