rbbcode 0.1.11 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,117 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- module RbbCode
4
- class RootNode
5
- def == (other_node)
6
- self.class == other_node.class and self.children == other_node.children
7
- end
8
-
9
- def print_tree(indent = 0)
10
- output = ''
11
- indent.times { output << " " }
12
- output << 'ROOT'
13
- children.each do |child|
14
- output << "\n" << child.print_tree(indent + 1)
15
- end
16
- output << "\n/ROOT"
17
- output
18
- end
19
- end
20
-
21
- class TagNode
22
- def == (other_node)
23
- self.class == other_node.class and self.tag_name == other_node.tag_name and self.value == other_node.value and self.children == other_node.children
24
- end
25
-
26
- def print_tree(indent = 0)
27
- output = ''
28
- indent.times { output << " " }
29
- if value.nil?
30
- output << "[#{tag_name}]"
31
- else
32
- output << "[#{tag_name}=#{value}]"
33
- end
34
- children.each do |child|
35
- output << "\n" << child.print_tree(indent + 1)
36
- end
37
- output << "\n"
38
- indent.times { output << " " }
39
- output << "[/#{tag_name}]"
40
- output
41
- end
42
- end
43
-
44
- class TextNode
45
- def == (other_node)
46
- self.class == other_node.class and self.text == other_node.text
47
- end
48
-
49
- def print_tree(indent = 0)
50
- output = ''
51
- indent.times { output << " " }
52
- output << '"' << text << '"'
53
- end
54
- end
55
- end
56
-
57
- class NodeBuilder
58
- include RbbCode
59
-
60
- def self.build(&block)
61
- builder = new
62
- builder.instance_eval(&block)
63
- builder.root
64
- end
65
-
66
- attr_reader :root
67
-
68
- protected
69
-
70
- def << (node)
71
- @current_parent.children << node
72
- end
73
-
74
- def initialize
75
- @root = RootNode.new
76
- @current_parent = @root
77
- end
78
-
79
- def text(contents, &block)
80
- self << TextNode.new(@current_parent, contents)
81
- end
82
-
83
- def tag(tag_name, value = nil, preformatted = false, &block)
84
- tag_node = TagNode.new(@current_parent, tag_name, value)
85
- tag_node.preformat! if preformatted
86
- self << tag_node
87
- original_parent = @current_parent
88
- @current_parent = tag_node
89
- instance_eval(&block)
90
- @current_parent = original_parent
91
- end
92
- end
93
-
94
- module NodeMatchers
95
- class MatchNode
96
- def initialize(expected_tree)
97
- @expected_tree = expected_tree
98
- end
99
-
100
- def matches?(target)
101
- @target = target
102
- @target == @expected_tree
103
- end
104
-
105
- def failure_message
106
- "Expected:\n\n#{@expected_tree.print_tree}\n\nbut got:\n\n#{@target.print_tree}"
107
- end
108
-
109
- def negative_failure_message
110
- "Expected anything other than:\n\n#{@expected_tree.print_tree}"
111
- end
112
- end
113
-
114
- def match_node(expected_node)
115
- MatchNode.new(expected_node)
116
- end
117
- end
data/spec/parser_spec.rb DELETED
@@ -1,163 +0,0 @@
1
- # coding: utf-8
2
- $KCODE = 'u'
3
-
4
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
5
-
6
- describe RbbCode::Parser do
7
- context '#parse' do
8
- before :each do
9
- @parser = RbbCode::Parser.new
10
- end
11
-
12
- it 'should create paragraphs and line breaks' do
13
- bb_code = "This is one paragraph.\n\nThis is another paragraph."
14
- @parser.parse(bb_code).should == '<p>This is one paragraph.</p><p>This is another paragraph.</p>'
15
- bb_code = "This is one line.\nThis is another line."
16
- @parser.parse(bb_code).should == '<p>This is one line.<br/>This is another line.</p>'
17
- end
18
-
19
- it 'should turn [b] to <strong>' do
20
- @parser.parse('This is [b]bold[/b] text').should == '<p>This is <strong>bold</strong> text</p>'
21
- end
22
-
23
- it 'should turn [i] to <em> by default' do
24
- @parser.parse('This is [i]italic[/i] text').should == '<p>This is <em>italic</em> text</p>'
25
- end
26
-
27
- it 'should turn [u] to <u>' do
28
- @parser.parse('This is [u]underlined[/u] text').should == '<p>This is <u>underlined</u> text</p>'
29
- end
30
-
31
- it 'should turn [url]http://google.com[/url] to a link' do
32
- @parser.parse('Visit [url]http://google.com[/url] now').should == '<p>Visit <a href="http://google.com">http://google.com</a> now</p>'
33
- end
34
-
35
- it 'should turn [url=http://google.com]Google[/url] to a link' do
36
- @parser.parse('Visit [url=http://google.com]Google[/url] now').should == '<p>Visit <a href="http://google.com">Google</a> now</p>'
37
- end
38
-
39
- it 'should turn [img] to <img>' do
40
- @parser.parse('[img]http://example.com/image.jpg[/img]').should == '<p><img src="http://example.com/image.jpg" alt=""/></p>'
41
- end
42
-
43
- it 'should parse nested tags' do
44
- @parser.parse('[b][i]This is bold-italic[/i][/b]').should == '<p><strong><em>This is bold-italic</em></strong></p>'
45
- end
46
-
47
- it 'should not put <p> tags around <ul> tags' do
48
- @parser.parse("Text.\n\n[list]\n[*]Foo[/*]\n[*]Bar[/*]\n[/list]\n\nMore text.").should == '<p>Text.</p><ul><li>Foo</li><li>Bar</li></ul><p>More text.</p>'
49
- end
50
-
51
- it 'should ignore forbidden or unrecognized tags' do
52
- @parser.parse('There is [foo]no such thing[/foo] as a foo tag').should == '<p>There is no such thing as a foo tag</p>'
53
- end
54
-
55
- it 'should recover gracefully from malformed or improperly matched tags' do
56
- @parser.parse('This [i/]tag[/i] is malformed').should == '<p>This [i/]tag is malformed</p>'
57
- @parser.parse('This [i]]tag[/i] is malformed').should == '<p>This <em>]tag</em> is malformed</p>'
58
- @parser.parse('This [i]tag[[/i] is malformed').should == '<p>This <em>tag[</em> is malformed</p>'
59
- @parser.parse('This [i]tag[//i] is malformed').should == '<p>This <em>tag[//i] is malformed</em></p>'
60
- @parser.parse('This [[i]tag[/i] is malformed').should == '<p>This [<em>tag</em> is malformed</p>'
61
- @parser.parse('This [i]tag[/i]] is malformed').should == '<p>This <em>tag</em>] is malformed</p>'
62
- @parser.parse('This [i]i tag[i] is not properly matched').should == '<p>This <em>i tag is not properly matched</em></p>'
63
- @parser.parse('This i tag[/i] is not properly matched').should == '<p>This i tag is not properly matched</p>'
64
- end
65
-
66
- it 'should escape < and >' do
67
- @parser.parse('This is [i]italic[/i], but this it not <i>italic</i>.').should == '<p>This is <em>italic</em>, but this it not &lt;i&gt;italic&lt;/i&gt;.</p>'
68
- end
69
-
70
- it 'should work when the string begins with a tag' do
71
- @parser.parse('[b]This is bold[/b]').should == '<p><strong>This is bold</strong></p>'
72
- end
73
-
74
- it 'should handle UTF8' do
75
- @parser.parse("Here's some UTF-8: [i]א[/i]. And here's some ASCII text.").should == "<p>Here's some UTF-8: <em>א</em>. And here's some ASCII text.</p>"
76
- end
77
-
78
- # Bugs reported and fixed:
79
-
80
- it 'should not leave an open <em> tag when parsing "foo [i][/i] bar"' do
81
- # Thanks to Vizakenjack for finding this. It creates an empty <em> tag. Browsers don't like this, so we need to replace it.
82
- @parser.parse('foo [i][/i] bar').should match(/<p>foo +bar<\/p>/)
83
- end
84
-
85
- it 'should not raise when parsing "Are you a real phan yet?\r\n\r\n[ ] Yes\r\n[X] No"' do
86
- # Thanks to sblackstone for finding this.
87
- @parser.parse("Are you a real phan yet?\r\n\r\n[ ] Yes\r\n[X] No")
88
- end
89
-
90
- it 'should support images inside links' do
91
- # Thanks to Vizakenjack for finding this.
92
- @parser.parse('[url=http://www.google.com][img]http://www.123.com/123.png[/img][/url]').should ==
93
- '<p><a href="http://www.google.com"><img src="http://www.123.com/123.png" alt=""/></a></p>'
94
- end
95
-
96
- it 'can parse phpBB-style [*] tags' do
97
- # Thanks to motiv for finding this
98
- @parser.parse("[list]\n[*]one\n[*]two\n[/list]"
99
- ).should == '<ul><li>one</li><li>two</li></ul>'
100
- end
101
-
102
- context 'parsing [code] tags' do
103
- # Thanks to fatalerrorx for finding these
104
- it 'wraps the <code> tags in <pre> tags' do
105
- @parser.parse('The [code]some code[/code] should be preformatted').should == '<p>The <pre><code>some code</code></pre> should be preformatted</p>'
106
- end
107
-
108
- it 'leaves line breaks inside untouched' do
109
- @parser.parse("Two lines of code:\n\n[code]line 1\n\nline 2[/code]\n\nAnd some more text.").should ==
110
- "<p>Two lines of code:</p><p><pre><code>line 1\n\nline 2</code></pre></p><p>And some more text.</p>"
111
- end
112
-
113
- it 'treats tags other than the closing tag as literals' do
114
- @parser.parse('[code]This is [b]bold[/b] text[/code]').should == '<p><pre><code>This is [b]bold[/b] text</code></pre></p>'
115
- end
116
- end
117
-
118
- # Leave tag support
119
-
120
- it 'should parse allowed leaf tags' do
121
- schema = RbbCode::Schema.new
122
- schema.allow_tag(:br)
123
- html_maker = CustomHtmlMaker.new
124
- @parser = RbbCode::Parser.new(:schema => schema, :html_maker => html_maker)
125
-
126
- @parser.parse('This text should contain a [:br] HTML tag').should == '<p>This text should contain a <br /> HTML tag</p>'
127
- end
128
-
129
- # Bug from original version
130
- it 'should not parse multiple not closing tags' do
131
- schema = RbbCode::Schema.new
132
- schema.allow_tag(:Qsmiley)
133
- html_maker = CustomHtmlMaker.new
134
- @parser = RbbCode::Parser.new(:schema => schema, :html_maker => html_maker)
135
-
136
- @parser.parse('Two smileys: 1) [Qsmiley] and 2) [Qsmiley]').should_not == '<p>Two smileys: 1) <smiley /> and 2) <smiley /></p>'
137
- end
138
-
139
- it 'should parse multiple allowed leaf tags' do
140
- schema = RbbCode::Schema.new
141
- schema.allow_tag(:br)
142
- html_maker = CustomHtmlMaker.new
143
- @parser = RbbCode::Parser.new(:schema => schema, :html_maker => html_maker)
144
-
145
- @parser.parse('This text should contain a [:br] HTML tag and another one [:br]').should == '<p>This text should contain a <br /> HTML tag and another one <br /></p>'
146
- end
147
-
148
- it 'should parse unknown leaf tags as text' do
149
- @parser.parse('This text should contain a [:pseudo] BBCode tag').should == '<p>This text should contain a [:pseudo] BBCode tag</p>'
150
- end
151
-
152
- # Bugs
153
-
154
- it 'should omit empty quotes' do
155
- @parser.parse("[quote][/quote]").should == ""
156
- end
157
-
158
- it 'should parse empty codes' do
159
- @parser.parse("[code][/code]").should == "<p><pre><code></code></pre></p>"
160
- end
161
-
162
- end
163
- end
data/spec/schema_spec.rb DELETED
@@ -1,100 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
-
5
- describe RbbCode::Schema do
6
- before :each do
7
- @schema = RbbCode::Schema.new
8
- @schema.clear
9
- @schema.allow_tags(*RbbCode::DEFAULT_ALLOWED_TAGS)
10
- end
11
-
12
- it 'should allow the default tags at the top level' do
13
- schema = RbbCode::Schema.new
14
- [
15
- 'b',
16
- 'i',
17
- 'u',
18
- 'url',
19
- 'img',
20
- 'code',
21
- 'quote',
22
- 'list'
23
- ].each do |tag|
24
- schema.tag(tag).valid_in_context?().should == true
25
- end
26
- end
27
-
28
- it 'should not allow unknown tags' do
29
- @schema.tag('foo').valid_in_context?().should == false
30
- end
31
-
32
- it 'should return a new SchemaTag object when tag is called' do
33
- @schema.tag('b').should be_a(RbbCode::SchemaTag)
34
- end
35
-
36
- it 'should not allow nesting a tag when may_not_be_nested is called on it' do
37
- @schema.tag('b').may_not_be_nested
38
- @schema.tag('b').valid_in_context?('b').should == false
39
- end
40
-
41
- it 'should allow nesting a tag when may_be_nested is called on it' do
42
- @schema.tag('b').may_not_be_nested
43
- @schema.tag('b').may_be_nested
44
- @schema.tag('b').valid_in_context?('b').should == true
45
- end
46
-
47
- it 'should not allow a tag to descend from another when forbidden by may_not_descend_from' do
48
- @schema.tag('b').may_not_descend_from('u')
49
- @schema.tag('b').valid_in_context?('u').should == false
50
- end
51
-
52
- it 'should allow a tag to descend from another when permitted by may_descend_from' do
53
- @schema.tag('b').may_not_descend_from('u')
54
- @schema.tag('b').may_descend_from('u')
55
- @schema.tag('b').valid_in_context?('u').should == true
56
- end
57
-
58
- it 'should not allow a tag to descend from anything other than the tags specified in must_be_child_of' do
59
- @schema.tag('b').must_be_child_of('u', 'quote')
60
- @schema.tag('b').valid_in_context?('i').should == false
61
- @schema.tag('b').valid_in_context?('u').should == true
62
- @schema.tag('b').valid_in_context?('quote').should == true
63
- end
64
-
65
- it 'should allow a tag to descend from the one specified in must_be_child_of' do
66
- @schema.tag('b').may_not_descend_from('u')
67
- @schema.tag('b').must_be_child_of('u')
68
- @schema.tag('b').valid_in_context?('u').should == true
69
- end
70
-
71
- it 'should not require a tag to be a child of another when need_not_be_child_of is called' do
72
- @schema.tag('b').must_be_child_of('u')
73
- @schema.tag('b').need_not_be_child_of('u')
74
- @schema.tag('b').valid_in_context?('i').should == true
75
- end
76
-
77
- it 'should allow only the specified tag as a child when may_only_be_parent_of is called' do
78
- @schema.tag('list').may_only_be_parent_of('*')
79
- @schema.tag('*').valid_in_context?('list').should == true
80
- @schema.tag('u').valid_in_context?('list').should == false
81
- @schema.tag('u').valid_in_context?('*', 'list').should == true
82
- end
83
-
84
- it 'should not allow text inside a tag when may_not_contain_text is called' do
85
- @schema.tag('list').may_not_contain_text
86
- @schema.text.valid_in_context?('list').should == false
87
- end
88
-
89
- it 'should allow text inside a tag when may_contain_text is called' do
90
- @schema.tag('list').may_not_contain_text
91
- @schema.tag('list').may_contain_text
92
- @schema.text.valid_in_context?('list').should == true
93
- end
94
-
95
- it 'should not allow text or children when must_be_empty is called' do
96
- @schema.tag('br').must_be_empty
97
- @schema.text.valid_in_context?('br').should == false
98
- @schema.tag('b').valid_in_context?('br').should == false
99
- end
100
- end
data/spec/spec_helper.rb DELETED
@@ -1,17 +0,0 @@
1
- require 'rubygems'
2
- require 'test/unit'
3
- require 'rspec'
4
-
5
- require File.expand_path(File.dirname(__FILE__) + '/../lib/rbbcode')
6
-
7
- class CustomHtmlMaker < RbbCode::HtmlMaker
8
-
9
- def html_from_br_tag(node)
10
- '<br />'
11
- end
12
-
13
- def html_from_Qsmiley_tag(node)
14
- '<smiley />'
15
- end
16
-
17
- end
@@ -1,123 +0,0 @@
1
- # encoding: utf-8
2
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
- require File.expand_path(File.dirname(__FILE__) + '/node_spec_helper')
4
- require 'pp'
5
-
6
- describe RbbCode::TreeMaker do
7
- include NodeMatchers
8
-
9
- context '#make_tree' do
10
- def expect_tree(str, &block)
11
- expected = NodeBuilder.build(&block)
12
- @tree_maker.make_tree(str).should match_node(expected)
13
- end
14
-
15
- before :each do
16
- @schema = RbbCode::Schema.new
17
- @tree_maker = RbbCode::TreeMaker.new(@schema)
18
- end
19
-
20
- it 'makes a tree from a string with one tag' do
21
- str = 'This is [b]bold[/b] text'
22
-
23
- expect_tree(str) do
24
- tag('p') do
25
- text 'This is '
26
- tag('b') { text 'bold' }
27
- text ' text'
28
- end
29
- end
30
- end
31
-
32
- it 'ignores tags that are invalid in their context' do
33
- @schema.tag('u').may_not_descend_from('b')
34
-
35
- str = 'This is [b]bold and [u]underlined[/u][/b] text'
36
-
37
- expect_tree(str) do
38
- tag('p') do
39
- text 'This is '
40
- tag('b') do
41
- text 'bold and '
42
- text 'underlined'
43
- end
44
- text ' text'
45
- end
46
- end
47
- end
48
-
49
- it 'creates paragraph tags' do
50
- str = "This is a paragraph.\n\nThis is another."
51
-
52
- expect_tree(str) do
53
- tag('p') do
54
- text 'This is a paragraph.'
55
- end
56
- tag('p') do
57
- text 'This is another.'
58
- end
59
- end
60
- end
61
-
62
- it 'does not put block-level elements inside paragraph tags' do
63
- str = "This is a list:\n\n[list]\n\n[*]Foo[/i]\n\n[/list]\n\nwith some text after it"
64
-
65
- expect_tree(str) do
66
- tag('p') do
67
- text 'This is a list:'
68
- end
69
- tag('list') do
70
- tag('*') { text 'Foo' }
71
- end
72
- tag('p') do
73
- text 'with some text after it'
74
- end
75
- end
76
- end
77
-
78
- it 'does not insert br tags in the midst of block-level elements' do
79
- str = "List:\n[list]\n[*]Foo[/*]\n[*]Bar[/*]\n[/list]\nText after list"
80
-
81
- expect_tree(str) do
82
- tag('p') do
83
- text 'List:'
84
- end
85
- tag('list') do
86
- tag('*') { text 'Foo' }
87
- tag('*') { text 'Bar' }
88
- end
89
- tag('p') do
90
- text 'Text after list'
91
- end
92
- end
93
- end
94
-
95
- it 'stores tag values' do
96
- str = 'This is a [url=http://google.com]link[/url]'
97
-
98
- expect_tree(str) do
99
- tag('p') do
100
- text 'This is a '
101
- tag('url', 'http://google.com') do
102
- text 'link'
103
- end
104
- end
105
- end
106
- end
107
-
108
- it 'auto-closes twins when the schema says it should' do
109
- str = "[list]\n[*]One\n[*]Two\n[/list]"
110
-
111
- expect_tree(str) do
112
- tag('list') do
113
- tag('*') do
114
- text 'One'
115
- end
116
- tag('*') do
117
- text 'Two'
118
- end
119
- end
120
- end
121
- end
122
- end
123
- end