rubb 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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