ruby-bbcode-to-md 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module RubyBbcode
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,113 @@
1
+ module RubyBBCode
2
+ module Tags
3
+ # tagname => tag, HTML open tag, HTML close tag, description, example
4
+ # All of these entrys are represented as @dictionary in the classes (or as the variable tags)
5
+ # A single item from this file (eg the :b entry) is refered to as a @definition
6
+ @@tags = {
7
+ :b => {
8
+ :html_open => '**', :html_close => '**',
9
+ :description => 'Make text bold',
10
+ :example => 'This is [b]bold[/b].'},
11
+ :i => {
12
+ :html_open => '*', :html_close => '*',
13
+ :description => 'Make text italic',
14
+ :example => 'This is [i]italic[/i].'},
15
+ :u => {
16
+ :html_open => '', :html_close => '',
17
+ :description => 'Underline text',
18
+ :example => 'This is [u]underlined[/u].'},
19
+ :center => {
20
+ :html_open => '', :html_close => '',
21
+ :description => 'Center a text',
22
+ :example => '[center]This is centered[/center].'},
23
+ :ul => {
24
+ :html_open => '', :html_close => "\n",
25
+ :description => 'Unordered list',
26
+ :example => '[ul][li]List item[/li][li]Another list item[/li][/ul].',
27
+ :only_allow => [ :li ]},
28
+ :ol => {
29
+ :html_open => '', :html_close => "\n",
30
+ :description => 'Ordered list',
31
+ :example => '[ol][li]List item[/li][li]Another list item[/li][/ol].',
32
+ :only_allow => [ :li ]},
33
+ :li => {
34
+ :html_open => {
35
+ :ul => ' - ',
36
+ :ol => ' 1. '
37
+ },
38
+ :html_close => "\n",
39
+ :description => 'List item',
40
+ :example => '[ul][li]List item[/li][li]Another list item[/li][/ul].',
41
+ :only_in => [ :ul, :ol ]},
42
+ :img => {
43
+ :html_open => '%between%', :html_close => '',
44
+ :description => 'Image',
45
+ :example => '[img]http://www.google.com/intl/en_ALL/images/logo.gif[/img].',
46
+ :only_allow => [],
47
+ :require_between => true,
48
+ :allow_tag_param => true, :allow_tag_param_between => false,
49
+ :tag_param => /^(\d*)x(\d*)$/,
50
+ :tag_param_tokens => [{:token => :width, :prefix => 'width="', :postfix => '" ' },
51
+ { :token => :height, :prefix => 'height="', :postfix => '" ' } ],
52
+ :tag_param_description => 'The image parameters \'%param%\' are incorrect, <width>x<height> excepted'},
53
+ :url => {
54
+ :html_open => '%url%', :html_close => '',
55
+ :description => 'Link to another page',
56
+ :example => '[url]http://www.google.com/[/url].',
57
+ :only_allow => [],
58
+ :require_between => true,
59
+ :allow_tag_param => true, :allow_tag_param_between => true,
60
+ :tag_param => /^((((http|https|ftp):\/\/)|\/).+)$/, :tag_param_tokens => [{ :token => :url }],
61
+ :tag_param_description => 'The URL should start with http:// https://, ftp:// or /, instead of \'%param%\'' },
62
+ :quote => {
63
+ :first_html_open => "\n", :last_html_close => "\n",
64
+ :html_open => "%author%>", :html_close => "\n",
65
+ :description => 'Quote another person',
66
+ :example => '[quote]BBCode is great[/quote]',
67
+ :allow_tag_param => true, :allow_tag_param_between => false,
68
+ :tag_param => /(.*)/,
69
+ :tag_param_tokens => [{:token => :author, :prefix => '>', :postfix => " said:\n"}]},
70
+ :size => {
71
+ :html_open => '[size=%size%]', :html_close => '[/size]',
72
+ :description => 'Change the size of the text',
73
+ :example => '[size=32]This is 32px[/size]',
74
+ :allow_tag_param => true, :allow_tag_param_between => false,
75
+ :tag_param => /(\d*)/,
76
+ :tag_param_tokens => [{:token => :size}]},
77
+ :color => {
78
+ :html_open => '', :html_close => '',
79
+ :description => 'Change the color of the text',
80
+ :example => '[color=red]This is red[/color]',
81
+ :allow_tag_param => true, :allow_tag_param_between => false,
82
+ :tag_param => /(([a-z]+)|(#[0-9a-f]{6}))/i,
83
+ :tag_param_tokens => [{:token => :color}]},
84
+ :youtube => {
85
+ :html_open => 'http://www.youtube.com/v/%between%', :html_close => '',
86
+ :description => 'Youtube video',
87
+ :example => '[youtube]E4Fbk52Mk1w[/youtube]',
88
+ :only_allow => [],
89
+ :url_varients => ["youtube.com", "youtu.be", "y2u.be"], # NOT USED
90
+ :url_matches => [/youtube\.com.*[v]=([^&]*)/, /youtu\.be\/([^&]*)/, /y2u\.be\/([^&]*)/],
91
+ :require_between => true},
92
+ :vimeo => {
93
+ :html_open => 'http://vimeo.com/%between%',
94
+ :html_close => '',
95
+ :description => 'Vimeo video',
96
+ :example => '[vimeo]http://vimeo.com/46141955[/vimeo]',
97
+ :only_allow => [],
98
+ :url_matches => [/vimeo\.com\/([^&]*)/],
99
+ :require_between => true},
100
+ :media => {
101
+ :multi_tag => true,
102
+ :supported_tags => [
103
+ :youtube,
104
+ :vimeo
105
+ ]
106
+ }
107
+ }
108
+
109
+ def self.tag_list
110
+ @@tags
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+ require 'benchmark'
3
+
4
+
5
+
6
+ class RubyBbcodeTest < Test::Unit::TestCase
7
+
8
+ end
@@ -0,0 +1,208 @@
1
+ require 'test_helper'
2
+
3
+ class RubyBbcodeTest < Test::Unit::TestCase
4
+
5
+ def test_multiline
6
+ assert_equal "line1\nline2", "line1\nline2".bbcode_to_md
7
+ assert_equal "line1\nline2", "line1\r\nline2".bbcode_to_md
8
+ end
9
+
10
+ def test_strong
11
+ assert_equal '**simple**', '[b]simple[/b]'.bbcode_to_md
12
+ assert_equal "**line 1\nline 2**", "**line 1\nline 2**".bbcode_to_md
13
+ end
14
+
15
+ def test_em
16
+ assert_equal '*simple*', '[i]simple[/i]'.bbcode_to_md
17
+ assert_equal "*line 1\nline 2*", "[i]line 1\nline 2[/i]".bbcode_to_md
18
+ end
19
+
20
+ def test_u
21
+ assert_equal 'simple', '[u]simple[/u]'.bbcode_to_md
22
+ assert_equal "line 1\nline 2", "[u]line 1\nline 2[/u]".bbcode_to_md
23
+ end
24
+
25
+ def test_size
26
+ assert_equal '[size=32]32px Text[/size]', '[size=32]32px Text[/size]'.bbcode_to_md
27
+ end
28
+
29
+ def test_color
30
+ assert_equal 'Red Text', '[color=red]Red Text[/color]'.bbcode_to_md
31
+ assert_equal 'Hex Color Text', '[color=#ff0023]Hex Color Text[/color]'.bbcode_to_md
32
+ end
33
+
34
+ def test_center
35
+ assert_equal 'centered', '[center]centered[/center]'.bbcode_to_md
36
+ end
37
+
38
+ def test_ordered_list
39
+ assert_equal " 1. item 1\n 1. item 2\n\n", '[ol][li]item 1[/li][li]item 2[/li][/ol]'.bbcode_to_md
40
+ end
41
+
42
+ def test_unordered_list
43
+ assert_equal " - item 1\n - item 2\n\n", '[ul][li]item 1[/li][li]item 2[/li][/ul]'.bbcode_to_md
44
+ end
45
+
46
+ def test_two_lists
47
+ assert_equal " - item1\n - item2\n\n - item1\n - item2\n\n",
48
+ "[ul][li]item1[/li][li]item2[/li][/ul][ul][li]item1[/li][li]item2[/li][/ul]".bbcode_to_md
49
+ end
50
+
51
+ def test_whitespace_in_only_allowed_tags
52
+ assert_equal "\n 1. item 1\n\n 1. item 2\n\n\n",
53
+ "[ol]\n[li]item 1[/li]\n[li]item 2[/li]\n[/ol]".bbcode_to_md
54
+ assert_equal " 1. item 1\n 1. item 2\n\n",
55
+ "[ol] [li]item 1[/li] [li]item 2[/li][/ol]".bbcode_to_md
56
+
57
+ end
58
+
59
+ def test_quote
60
+ assert_equal "\n>quoting\n\n", '[quote]quoting[/quote]'.bbcode_to_md
61
+ assert_equal "\n>someone said:\n>quoting\n\n", '[quote=someone]quoting[/quote]'.bbcode_to_md
62
+ end
63
+
64
+ def test_nested_quotes
65
+ assert_equal "\n>Kitten said:\n>>creatiu said:\n>>f1\n>f2",
66
+ '[quote=Kitten][quote=creatiu]f1[/quote]f2[/quote]'.bbcode_to_md
67
+ end
68
+
69
+ # TODO convert URLs with link text instead of just extracting the url.
70
+ def test_link
71
+ assert_equal 'http://www.google.com', '[url]http://www.google.com[/url]'.bbcode_to_md
72
+ assert_equal 'http://google.com', '[url=http://google.com]Google[/url]'.bbcode_to_md
73
+ assert_equal '/index.html', '[url=/index.html]Home[/url]'.bbcode_to_md
74
+ assert_equal "http://google.com and http://bing.com are both search engines.",
75
+ '[url=http://google.com]Google[/url] and [url=http://bing.com]Bing[/url] are both search engines.'.bbcode_to_md
76
+ end
77
+
78
+ def test_image
79
+ assert_equal 'http://www.ruby-lang.org/images/logo.gif',
80
+ '[img]http://www.ruby-lang.org/images/logo.gif[/img]'.bbcode_to_md
81
+ assert_equal 'http://www.ruby-lang.org/images/logo.gif',
82
+ '[img=95x96]http://www.ruby-lang.org/images/logo.gif[/img]'.bbcode_to_md
83
+ end
84
+
85
+ def test_youtube
86
+ assert_equal 'http://www.youtube.com/v/E4Fbk52Mk1w' ,
87
+ '[youtube]E4Fbk52Mk1w[/youtube]'.bbcode_to_md
88
+ end
89
+
90
+ def test_youtube_with_full_url
91
+ full_url = "http://www.youtube.com/watch?feature=player_embedded&v=E4Fbk52Mk1w"
92
+ assert_equal "http://www.youtube.com/v/E4Fbk52Mk1w" ,
93
+ "[youtube]#{full_url}[/youtube]".bbcode_to_md
94
+ end
95
+
96
+ def test_youtube_with_url_shortener
97
+ full_url = "http://www.youtu.be/cSohjlYQI2A"
98
+ assert_equal "http://www.youtube.com/v/cSohjlYQI2A" ,
99
+ "[youtube]#{full_url}[/youtube]".bbcode_to_md
100
+ end
101
+
102
+
103
+ def test_html_escaping
104
+ assert_equal '**&lt;i&gt;foobar&lt;/i&gt;**', '[b]<i>foobar</i>[/b]'.bbcode_to_md
105
+ assert_equal '**<i>foobar</i>**', '[b]<i>foobar</i>[/b]'.bbcode_to_md(false)
106
+ assert_equal '1 is &lt; 2', '1 is < 2'.bbcode_to_md
107
+ assert_equal '1 is < 2', '1 is < 2'.bbcode_to_md(false)
108
+ assert_equal '2 is &gt; 1', '2 is > 1'.bbcode_to_md
109
+ assert_equal '2 is > 1', '2 is > 1'.bbcode_to_md(false)
110
+ end
111
+
112
+ def test_disable_tags
113
+ assert_equal "[b]foobar[/b]", "[b]foobar[/b]".bbcode_to_md(true, {}, :disable, :b)
114
+ assert_equal "[b]*foobar*[/b]", "[b][i]foobar[/i][/b]".bbcode_to_md(true, {}, :disable, :b)
115
+ assert_equal "[b][i]foobar[/i][/b]", "[b][i]foobar[/i][/b]".bbcode_to_md(true, {}, :disable, :b, :i)
116
+ end
117
+
118
+ def test_enable_tags
119
+ assert_equal "**foobar**" , "[b]foobar[/b]".bbcode_to_md(true, {}, :enable, :b)
120
+ assert_equal "**[i]foobar[/i]**", "[b][i]foobar[/i][/b]".bbcode_to_md(true, {}, :enable, :b)
121
+ assert_equal "***foobar***", "[b][i]foobar[/i][/b]".bbcode_to_md(true, {}, :enable, :b, :i)
122
+ end
123
+
124
+ def test_to_html_bang_method
125
+ foo = "[b]foobar[/b]"
126
+ assert_equal "**foobar**", foo.bbcode_to_md!
127
+ assert_equal "**foobar**", foo
128
+ end
129
+
130
+ # commented this out, it kinda just gets in the way of development atm
131
+ #def test_self_tag_list
132
+ # assert_equal 16, RubyBBCode::Tags.tag_list.size
133
+ #end
134
+
135
+ def test_addition_of_tags
136
+ mydef = {
137
+ :test => {
138
+ :html_open => '<test>', :html_close => '</test>',
139
+ :description => 'This is a test',
140
+ :example => '[test]Test here[/test]'}
141
+ }
142
+ assert_equal 'pre <test>Test here</test> post', 'pre [test]Test here[/test] post'.bbcode_to_md(true, mydef)
143
+ assert_equal 'pre **<test>Test here</test>** post', 'pre [b][test]Test here[/test][/b] post'.bbcode_to_md(true, mydef)
144
+ end
145
+
146
+ def test_multiple_tag_test
147
+ assert_equal "**bold***italic*underline\n>quote\n\nhttps://test.com",
148
+ "[b]bold[/b][i]italic[/i][u]underline[/u][quote]quote[/quote][url=https://test.com]link[/url]".bbcode_to_md
149
+ end
150
+
151
+ def test_no_ending_tag
152
+ assert_raise RuntimeError do
153
+ "this [b]should not be bold".bbcode_to_md
154
+ end
155
+ end
156
+
157
+ def test_no_start_tag
158
+ assert_raise RuntimeError do
159
+ "this should not be bold[/b]".bbcode_to_md
160
+ end
161
+ end
162
+
163
+ def test_different_start_and_ending_tags
164
+ assert_raise RuntimeError do
165
+ "this [b]should not do formatting[/i]".bbcode_to_md
166
+ end
167
+ end
168
+
169
+ # TODO: This stack level problem should be validated during the validations
170
+ def test_stack_level_too_deep
171
+ num = 2300 # increase this number if the test starts failing. It's very near the tipping point
172
+ openers = "[s]hi i'm" * num
173
+ closers = "[/s]" * num
174
+ assert_raise( RuntimeError ) do
175
+ (openers+closers).bbcode_to_md
176
+ end
177
+
178
+ end
179
+
180
+ def test_mulit_tag
181
+ input1 = "[media]http://www.youtube.com/watch?v=cSohjlYQI2A[/media]"
182
+ input2 = "[media]http://vimeo.com/46141955[/media]"
183
+
184
+ output1 = "http://www.youtube.com/v/cSohjlYQI2A"
185
+ output2 = "http://vimeo.com/46141955"
186
+
187
+ assert_equal output1, input1.bbcode_to_md
188
+ assert_equal output2, input2.bbcode_to_md
189
+ end
190
+
191
+ def test_vimeo_tag
192
+ input = "[vimeo]http://vimeo.com/46141955[/vimeo]"
193
+ input2 = "[vimeo]46141955[/vimeo]"
194
+ output = 'http://vimeo.com/46141955'
195
+
196
+ assert_equal output, input.bbcode_to_md
197
+ assert_equal output, input2.bbcode_to_md
198
+ end
199
+
200
+ def test_failing_multi_tag
201
+ input1 = "[media]http://www.youtoob.com/watch?v=cSohjlYQI2A[/media]"
202
+
203
+ assert_equal input1, input1.bbcode_to_md
204
+ end
205
+
206
+
207
+
208
+ end
@@ -0,0 +1,18 @@
1
+ require 'ruby-bbcode'
2
+ require "test/unit"
3
+
4
+ # This hack allows us to make all the private methods of a class public.
5
+ class Class
6
+ def publicize_methods
7
+ saved_private_instance_methods = self.private_instance_methods
8
+ self.class_eval { public(*saved_private_instance_methods) }
9
+ yield
10
+ self.class_eval { private(*saved_private_instance_methods) }
11
+ end
12
+ end
13
+
14
+
15
+ # This is for measuring memory usage...
16
+ def get_current_memory_usage
17
+ `ps -o rss= -p #{Process.pid}`.to_i
18
+ end
@@ -0,0 +1,47 @@
1
+ require 'test_helper'
2
+
3
+ class RubyBbcodeTest < Test::Unit::TestCase
4
+ include ::RubyBBCode::Tags
5
+
6
+ def test_bbtree_to_v
7
+ text = "[i][b]a[/b][b]a[/b][b]a[/b][b]a[/b]item 1[/i][i]item 2[/i]"
8
+ visual = <<eos
9
+ i
10
+ b
11
+ "a"
12
+ b
13
+ "a"
14
+ b
15
+ "a"
16
+ b
17
+ "a"
18
+ "item 1"
19
+ i
20
+ "item 2"
21
+ eos
22
+
23
+ tags = @@tags
24
+ @tag_sifter = RubyBBCode::TagSifter.new(text, tags)
25
+ @tag_sifter.process_text
26
+
27
+ # manually include the debugging methods if they've been disabled for cleanliness purposes
28
+ @tag_sifter.bbtree.extend(::RubyBBCode::DebugBBTree) unless @tag_sifter.bbtree.respond_to? :to_v
29
+
30
+ assert_equal visual, @tag_sifter.bbtree.to_v
31
+ end
32
+
33
+ def test_bbtree_counting_nodes
34
+ text = "[ol][li][b][/b][b][/b][b][/b][b][/b]item 1[/li][li]item 2[/li][/ol]"
35
+ tags = @@tags
36
+
37
+ @tag_sifter = RubyBBCode::TagSifter.new(text, tags)
38
+
39
+ @tag_sifter.process_text
40
+
41
+ # manually include debugging methods if needed.
42
+ @tag_sifter.bbtree.extend(::RubyBBCode::DebugBBTree) unless @tag_sifter.bbtree.respond_to? :count_child_nodes
43
+
44
+ assert_equal 9, @tag_sifter.bbtree.count_child_nodes
45
+ end
46
+
47
+ end
@@ -0,0 +1,51 @@
1
+ require 'test_helper'
2
+
3
+ class TagSifterTest < Test::Unit::TestCase
4
+ def test_youtube_parser
5
+ url1 = "http://www.youtube.com/watch?v=E4Fbk52Mk1w"
6
+ just_an_id = 'E4Fbk52Mk1w'
7
+ url_without_http = "www.youtube.com/watch?v=E4Fbk52Mk1w"
8
+ url_without_www = "youtube.com/watch?v=E4Fbk52Mk1w"
9
+ url_with_feature = "http://www.youtube.com/watch?feature=player_embedded&v=E4Fbk52Mk1w"
10
+ mock_regex_matches = [/youtube.com.*[v]=([^&]*)/, /youtu.be\/([^&]*)/, /y2u.be\/([^&]*)/]
11
+
12
+ expected_output = 'E4Fbk52Mk1w'
13
+
14
+ RubyBBCode::TagSifter.publicize_methods do
15
+ ts = RubyBBCode::TagSifter.new "", ""
16
+ assert_equal expected_output,
17
+ ts.conduct_special_formatting(url1, mock_regex_matches)
18
+
19
+ assert_equal expected_output,
20
+ ts.conduct_special_formatting(just_an_id, mock_regex_matches)
21
+
22
+ assert_equal expected_output,
23
+ ts.conduct_special_formatting(url_without_http, mock_regex_matches)
24
+
25
+ assert_equal expected_output,
26
+ ts.conduct_special_formatting(url_without_www, mock_regex_matches)
27
+
28
+ assert_equal expected_output,
29
+ ts.conduct_special_formatting(url_with_feature, mock_regex_matches)
30
+ end
31
+
32
+ end
33
+
34
+ # I think the answer to this is creating a new tag named [youtube]
35
+ # but that captures specifically the .be or .com and treats them differently...
36
+ def test_youtubes_via_there_url_shortener
37
+ url_from_shortener = "http://youtu.be/E4Fbk52Mk1w"
38
+ directory_format = "http://youtube.googleapis.com/v/E4Fbk52Mk1w"
39
+ expected_output = 'E4Fbk52Mk1w'
40
+ mock_regex_matches = [/youtube.com.*[v]=([^&]*)/, /youtu.be\/([^&]*)/, /y2u.be\/([^&]*)/]
41
+
42
+
43
+ RubyBBCode::TagSifter.publicize_methods do
44
+ ts = RubyBBCode::TagSifter.new "", ""
45
+
46
+
47
+ assert_equal expected_output,
48
+ ts.conduct_special_formatting(url_from_shortener, mock_regex_matches) # this test is now hopelessly broken because generating an ID from a link requires that @bbtree.current_node.definition be properly populated with regex matches...
49
+ end
50
+ end
51
+ end