bbcoder 0.1.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/.gemtest +0 -0
- data/.rspec +2 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +20 -0
- data/LICENSE +20 -0
- data/README.md +76 -0
- data/Rakefile +19 -0
- data/bbcoder.gemspec +24 -0
- data/lib/bbcoder/base.rb +39 -0
- data/lib/bbcoder/buffer.rb +30 -0
- data/lib/bbcoder/buffer_tags.rb +77 -0
- data/lib/bbcoder/configuration.rb +20 -0
- data/lib/bbcoder/string.rb +5 -0
- data/lib/bbcoder/tag.rb +62 -0
- data/lib/bbcoder/version.rb +3 -0
- data/lib/bbcoder.rb +63 -0
- data/spec/base_spec.rb +46 -0
- data/spec/bbcoder_spec.rb +61 -0
- data/spec/buffer_spec.rb +42 -0
- data/spec/buffer_tags_spec.rb +47 -0
- data/spec/spec_helper.rb +11 -0
- metadata +115 -0
data/.gemtest
ADDED
File without changes
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.1.2)
|
5
|
+
rr (1.0.2)
|
6
|
+
rspec (2.4.0)
|
7
|
+
rspec-core (~> 2.4.0)
|
8
|
+
rspec-expectations (~> 2.4.0)
|
9
|
+
rspec-mocks (~> 2.4.0)
|
10
|
+
rspec-core (2.4.0)
|
11
|
+
rspec-expectations (2.4.0)
|
12
|
+
diff-lcs (~> 1.1.2)
|
13
|
+
rspec-mocks (2.4.0)
|
14
|
+
|
15
|
+
PLATFORMS
|
16
|
+
ruby
|
17
|
+
|
18
|
+
DEPENDENCIES
|
19
|
+
rr
|
20
|
+
rspec
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 John "asceth" Long
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
'Software'), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
17
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
18
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
19
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
20
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
Features
|
2
|
+
--------
|
3
|
+
|
4
|
+
* Non-regex based (except for the split)
|
5
|
+
* Handles deep nesting of tags
|
6
|
+
* Generates good html even from bad input
|
7
|
+
* Easy configuration to add new tags
|
8
|
+
|
9
|
+
* Tags supported:
|
10
|
+
|
11
|
+
p, b, i, u, s, del, ins, ol, ul, li, dl, dt, dd, quote, code, spoiler, url, img
|
12
|
+
|
13
|
+
Usage
|
14
|
+
--------
|
15
|
+
|
16
|
+
BBCoder.new(text).to_html
|
17
|
+
# or
|
18
|
+
"[p]my string[/p]".bbcode_to_html
|
19
|
+
|
20
|
+
Install
|
21
|
+
-------
|
22
|
+
|
23
|
+
gem install bbcoder
|
24
|
+
|
25
|
+
|
26
|
+
Configuration
|
27
|
+
-----------------------
|
28
|
+
|
29
|
+
BBCoder.configure do
|
30
|
+
tag :b, :as => :strong
|
31
|
+
|
32
|
+
tag :ul
|
33
|
+
tag :ol
|
34
|
+
tag :li, :parents => [:ol, :ul]
|
35
|
+
|
36
|
+
tag :img, :match => /^.*(png|bmp|jpg|gif)$/ do
|
37
|
+
%(<a href="#{content}"><img src="#{content}" /></a>)
|
38
|
+
end
|
39
|
+
|
40
|
+
tag :code do
|
41
|
+
<<-EOS
|
42
|
+
<div class="bbcode-code #{meta}">
|
43
|
+
<pre>#{content}</pre>
|
44
|
+
</div>
|
45
|
+
EOS
|
46
|
+
end
|
47
|
+
|
48
|
+
tag :url do
|
49
|
+
if meta.nil? || meta.empty?
|
50
|
+
%(<a href="#{content}">#{content}</a>)
|
51
|
+
else
|
52
|
+
%(<a href="#{meta}">#{content}</a>)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
Options for #tag
|
59
|
+
|
60
|
+
* :as (symbol) -> use this as the html element ([b] becomes strong)
|
61
|
+
* :match (regex) -> convert this tag and its content to html only if the content matches the regex
|
62
|
+
* :parents ([symbol]) -> ignore this tag if there is no open tag that matches its parents
|
63
|
+
|
64
|
+
|
65
|
+
When you pass a block to #tag it is expecting you to return a string. You have two variables available to your block:
|
66
|
+
|
67
|
+
* meta -> Everything after the '=' in the opening tag (with [quote="Legendary"] meta returns '"Legendary"' and with [quote] meta returns nil)
|
68
|
+
* content -> Everything between the two tags (with [b]strong arm[/b] content returns 'strong arm')
|
69
|
+
|
70
|
+
|
71
|
+
Author
|
72
|
+
------
|
73
|
+
|
74
|
+
Original author: John "asceth" Long
|
75
|
+
|
76
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "bundler"
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
require "rspec"
|
5
|
+
require "rspec/core/rake_task"
|
6
|
+
|
7
|
+
Rspec::Core::RakeTask.new(:spec)
|
8
|
+
|
9
|
+
gemspec = eval(File.read(File.join(Dir.pwd, "bbcoder.gemspec")))
|
10
|
+
|
11
|
+
task :build => "#{gemspec.full_name}.gem"
|
12
|
+
|
13
|
+
task :test => :spec
|
14
|
+
|
15
|
+
file "#{gemspec.full_name}.gem" => gemspec.files + ["bbcoder.gemspec"] do
|
16
|
+
system "gem build bbcoder.gemspec"
|
17
|
+
system "gem install bbcoder-#{BBCoder::VERSION}.gem"
|
18
|
+
end
|
19
|
+
|
data/bbcoder.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "bbcoder/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "bbcoder"
|
6
|
+
s.version = BBCoder::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["John 'asceth' Long"]
|
9
|
+
s.email = ["machinist@asceth.com"]
|
10
|
+
s.homepage = "http://github.com/asceth/bbcoder"
|
11
|
+
s.summary = "BBCode parser"
|
12
|
+
s.description = "A gem for parsing bbcode that doesn't rely on regular expressions"
|
13
|
+
|
14
|
+
s.rubyforge_project = "bbcoder"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency 'rspec'
|
22
|
+
s.add_development_dependency 'rr'
|
23
|
+
end
|
24
|
+
|
data/lib/bbcoder/base.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
class BBCoder
|
2
|
+
attr_reader :raw
|
3
|
+
|
4
|
+
def self.configure(&block)
|
5
|
+
configuration.instance_eval(&block)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.configuration
|
9
|
+
@configuration ||= BBCoder::Configuration.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(text)
|
13
|
+
@raw = text.split(/(\[[^\]]+\])/i).select {|string| string.size > 0}
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_html
|
17
|
+
@html ||= parse
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse
|
21
|
+
raw.each do |data|
|
22
|
+
case data
|
23
|
+
when /\[\/([^\]]+)\]/
|
24
|
+
buffer.tags.pop($1.to_sym)
|
25
|
+
when /\[([^\]]+)\]/
|
26
|
+
buffer.tags.push($1)
|
27
|
+
else
|
28
|
+
buffer.push(data)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
buffer.join
|
33
|
+
end
|
34
|
+
|
35
|
+
def buffer
|
36
|
+
@buffer ||= BBCoder::Buffer.new
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class BBCoder
|
2
|
+
class Buffer
|
3
|
+
attr_accessor :_internal, :tags
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@_internal = {}
|
7
|
+
@tags = BBCoder::BufferTags.new(self)
|
8
|
+
end
|
9
|
+
|
10
|
+
def push(content)
|
11
|
+
_internal[depth] ||= ""
|
12
|
+
_internal[depth] += content
|
13
|
+
end
|
14
|
+
|
15
|
+
def pop(depth_modifier = 0)
|
16
|
+
_internal.delete(depth + depth_modifier)
|
17
|
+
end
|
18
|
+
|
19
|
+
# end of processing, insert any orphaned tags without conversion
|
20
|
+
def join
|
21
|
+
push(tags.join)
|
22
|
+
end
|
23
|
+
|
24
|
+
# delegates to tags
|
25
|
+
def depth
|
26
|
+
tags.size
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,77 @@
|
|
1
|
+
class BBCoder
|
2
|
+
class BufferTags
|
3
|
+
attr_accessor :buffer, :_internal, :_meta
|
4
|
+
|
5
|
+
def initialize(buffer)
|
6
|
+
@buffer = buffer
|
7
|
+
@_internal = []
|
8
|
+
@_meta = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def push(tag)
|
12
|
+
tag, meta = if tag.include?("=")
|
13
|
+
splits = tag.split("=")
|
14
|
+
[splits.shift.to_sym, splits.join]
|
15
|
+
else
|
16
|
+
[tag.to_sym, nil]
|
17
|
+
end
|
18
|
+
|
19
|
+
if criteria_met?(tag)
|
20
|
+
_internal.push(tag)
|
21
|
+
_meta[size] = meta
|
22
|
+
else
|
23
|
+
buffer.push(BBCoder::Tag.reform(tag, meta))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# logic when popping specific tag
|
28
|
+
def pop(tag)
|
29
|
+
if empty? || !include?(tag)
|
30
|
+
buffer.push("[/#{tag}]")
|
31
|
+
elsif last == tag
|
32
|
+
buffer.push(BBCoder::Tag.to_html(_internal.pop, _meta.delete(size+1), buffer.pop(+1)))
|
33
|
+
elsif include?(tag)
|
34
|
+
# repeats pop(tag) until we reach the last == tag
|
35
|
+
buffer.push(join(+1))
|
36
|
+
pop(tag)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# orphaned open tags are combined
|
41
|
+
def join(limit = nil)
|
42
|
+
limit = size if limit.nil?
|
43
|
+
|
44
|
+
1.upto(limit).to_a.collect do
|
45
|
+
[BBCoder::Tag.reform(_internal.pop, _meta.delete(size+1)), buffer.pop(+1)].join # +1 depth modifier for the buffer
|
46
|
+
end.reverse.join
|
47
|
+
end
|
48
|
+
|
49
|
+
# delegates to _internal
|
50
|
+
def size
|
51
|
+
_internal.size
|
52
|
+
end
|
53
|
+
|
54
|
+
def empty?
|
55
|
+
_internal.empty?
|
56
|
+
end
|
57
|
+
|
58
|
+
def last
|
59
|
+
_internal.last
|
60
|
+
end
|
61
|
+
|
62
|
+
def include?(tag)
|
63
|
+
_internal.include?(tag)
|
64
|
+
end
|
65
|
+
|
66
|
+
# helper methods
|
67
|
+
def criteria_met?(tag)
|
68
|
+
return false if BBCoder.configuration[tag].nil?
|
69
|
+
|
70
|
+
parent_criteria_met?(BBCoder.configuration[tag].parents)
|
71
|
+
end
|
72
|
+
|
73
|
+
def parent_criteria_met?(parents)
|
74
|
+
parents.empty? || !(_internal & parents).empty?
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class BBCoder
|
2
|
+
class Configuration
|
3
|
+
@@tags = {}
|
4
|
+
|
5
|
+
def [](value)
|
6
|
+
@@tags[value]
|
7
|
+
end
|
8
|
+
|
9
|
+
def tag(name, options = {}, &block)
|
10
|
+
unless block.nil?
|
11
|
+
block.binding.eval <<-EOS
|
12
|
+
def meta; @meta; end
|
13
|
+
def content; @content; end
|
14
|
+
EOS
|
15
|
+
end
|
16
|
+
@@tags[name.to_sym] = BBCoder::Tag.new(name.to_sym, options.merge(:block => block))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
data/lib/bbcoder/tag.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
class BBCoder
|
2
|
+
class Tag
|
3
|
+
attr_reader :name, :options
|
4
|
+
|
5
|
+
def initialize(name, options = {})
|
6
|
+
@name = name
|
7
|
+
@options = options.merge(:as => (options[:as] || name))
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_html(meta, content)
|
11
|
+
return self.class.reform(name, meta, content) unless content_valid?(content)
|
12
|
+
|
13
|
+
|
14
|
+
if options[:block].nil?
|
15
|
+
"<#{options[:as]}>#{content}</#{options[:as]}>"
|
16
|
+
else
|
17
|
+
options[:block].binding.eval <<-EOS
|
18
|
+
@meta = "#{meta}"
|
19
|
+
@content = "#{content}"
|
20
|
+
EOS
|
21
|
+
options[:block].call
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def content_valid?(content)
|
26
|
+
return true if options[:match].nil?
|
27
|
+
|
28
|
+
return !content.match(options[:match]).nil?
|
29
|
+
end
|
30
|
+
|
31
|
+
def parents
|
32
|
+
options[:parents] || []
|
33
|
+
end
|
34
|
+
|
35
|
+
module ClassMethods
|
36
|
+
def to_html(tag, meta, content)
|
37
|
+
BBCoder.configuration[tag].to_html(meta, content)
|
38
|
+
end
|
39
|
+
|
40
|
+
def reform(tag, meta, content = nil)
|
41
|
+
if content.nil?
|
42
|
+
%(#{reform_open(tag, meta)})
|
43
|
+
else
|
44
|
+
%(#{reform_open(tag, meta)}#{content}#{reform_end(tag)})
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def reform_open(tag, meta)
|
49
|
+
if meta.nil? || meta.empty?
|
50
|
+
"[#{tag}]"
|
51
|
+
else
|
52
|
+
"[#{tag}=#{meta}]"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def reform_end(tag)
|
57
|
+
"[/#{tag}]"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
extend ClassMethods
|
61
|
+
end
|
62
|
+
end
|
data/lib/bbcoder.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'bbcoder/base'
|
2
|
+
require 'bbcoder/configuration'
|
3
|
+
require 'bbcoder/tag'
|
4
|
+
require 'bbcoder/buffer'
|
5
|
+
require 'bbcoder/buffer_tags'
|
6
|
+
require 'bbcoder/string'
|
7
|
+
|
8
|
+
BBCoder.configure do
|
9
|
+
tag :p
|
10
|
+
tag :b, :as => :strong
|
11
|
+
tag :i, :as => :em
|
12
|
+
tag :u
|
13
|
+
tag :s, :as => :strike
|
14
|
+
tag :del
|
15
|
+
tag :ins
|
16
|
+
tag :ol
|
17
|
+
tag :ul
|
18
|
+
tag :li, :parents => [:ol, :ul]
|
19
|
+
tag :dl
|
20
|
+
tag :dt, :parents => [:dl]
|
21
|
+
tag :dd, :parents => [:dl]
|
22
|
+
|
23
|
+
tag :quote do
|
24
|
+
<<-EOS
|
25
|
+
<fieldset>
|
26
|
+
<legend>#{meta} says</legend>
|
27
|
+
<blockquote>
|
28
|
+
#{content}
|
29
|
+
</blockquote>
|
30
|
+
</fieldset>
|
31
|
+
EOS
|
32
|
+
end
|
33
|
+
|
34
|
+
tag :code do
|
35
|
+
<<-EOS
|
36
|
+
<div class="bbcode-code #{meta}">
|
37
|
+
<pre>#{content}</pre>
|
38
|
+
</div>
|
39
|
+
EOS
|
40
|
+
end
|
41
|
+
|
42
|
+
tag :spoiler do
|
43
|
+
<<-EOS
|
44
|
+
<fieldset class="bbcode-spoiler">
|
45
|
+
<legend>Spoiler</legend>
|
46
|
+
<div>#{content}</div>
|
47
|
+
</fieldset>
|
48
|
+
EOS
|
49
|
+
end
|
50
|
+
|
51
|
+
tag :url do
|
52
|
+
if meta.nil? || meta.empty?
|
53
|
+
%(<a href="#{content}">#{content}</a>)
|
54
|
+
else
|
55
|
+
%(<a href="#{meta}">#{content}</a>)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
tag :img, :match => /^.*(png|bmp|jpg|gif)$/ do
|
60
|
+
%(<a href="#{content}"><img src="#{content}" /></a>)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BBCoder do
|
4
|
+
|
5
|
+
subject { BBCoder.new("[p]Text and now [b]bolded.[/b][/p]") }
|
6
|
+
|
7
|
+
context "#configuration" do
|
8
|
+
it "should return the same object for multiple calls" do
|
9
|
+
BBCoder.configuration.should == BBCoder.configuration
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "#buffer" do
|
14
|
+
it "should return the same object for multiple calls" do
|
15
|
+
subject.buffer.should == subject.buffer
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "#configure" do
|
20
|
+
it "should fail without a block" do
|
21
|
+
lambda { BBCoder.configure }.should raise_error
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should instance_eval the block onto configuration" do
|
25
|
+
block = Proc.new { tag :p }
|
26
|
+
mock(BBCoder).configuration.stub!.instance_eval(&block)
|
27
|
+
BBCoder.configure(&block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "#initialize" do
|
32
|
+
it "should split tags up properly" do
|
33
|
+
subject.raw.should == ["[p]", "Text and now ", "[b]", "bolded.", "[/b]", "[/p]"]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "#parse" do
|
38
|
+
it "should loop through raw elements and join the buffer" do
|
39
|
+
mock(subject).raw.stub!.each {nil}
|
40
|
+
mock(subject).buffer.stub!.join {"output"}
|
41
|
+
|
42
|
+
subject.parse
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BBCoder do
|
4
|
+
|
5
|
+
context "with properly formatted input" do
|
6
|
+
it "should parse paragraph statements" do
|
7
|
+
"[p]Text and now [p]nested.[/p][/p]".bbcode_to_html.should == "<p>Text and now <p>nested.</p></p>"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should parse paragraph and bold statements" do
|
11
|
+
"[p]Text and now [b]nested.[/b][/p]".bbcode_to_html.should == "<p>Text and now <strong>nested.</strong></p>"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should parse a combination of statements" do
|
15
|
+
output = "[p]Text and now [b]bold then [i]italics[/i][/b][/p] and then a [quote]Quote[/quote]".bbcode_to_html
|
16
|
+
output.should == <<-EOS
|
17
|
+
<p>Text and now <strong>bold then <em>italics</em></strong></p> and then a <fieldset>
|
18
|
+
<legend> says</legend>
|
19
|
+
<blockquote>
|
20
|
+
Quote
|
21
|
+
</blockquote>
|
22
|
+
</fieldset>
|
23
|
+
EOS
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should handle multiple nestings of b elements" do
|
27
|
+
"[b]Now I [b] am [b] extremely [b] bold![/b][/b][/b][/b]".bbcode_to_html.should == "<strong>Now I <strong> am <strong> extremely <strong> bold!</strong></strong></strong></strong>"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with incorrectly formatted input" do
|
32
|
+
it "should ignore non-matched tag content" do
|
33
|
+
"[b][img]http://mybad.com[/img][/b]".bbcode_to_html.should == "<strong>[img]http://mybad.com[/img]</strong>"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should ignore tags without required parents" do
|
37
|
+
"[b]Strong list item [li]one of many[/li][/b]".bbcode_to_html.should == "<strong>Strong list item [li]one of many[/li]</strong>"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should ignore un-opened tags" do
|
41
|
+
"[p]Text aint it grand![/p][/p]".bbcode_to_html.should == "<p>Text aint it grand!</p>[/p]"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should ignore un-closed tags" do
|
45
|
+
"[p]Text aint it grand!".bbcode_to_html.should == "[p]Text aint it grand!"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should ignore un-closed and un-opened tags" do
|
49
|
+
"[p]Text aint it grand!".bbcode_to_html.should == "[p]Text aint it grand!"
|
50
|
+
end
|
51
|
+
|
52
|
+
it "shouldn't choke on extremely bad input" do
|
53
|
+
"[p]Text and [/b] with a [p] and [quote] a [/p] care in sight oh [i] my [/b].".bbcode_to_html.should == "[p]Text and [/b] with a <p> and [quote] a </p> care in sight oh [i] my [/b]."
|
54
|
+
end
|
55
|
+
|
56
|
+
it "shouldn't choke on extremely bad input with meta weirdness" do
|
57
|
+
"[p]Text and [/b] with a [p] and [quote='Hahah'] a [/p] care in sight oh [i=nometaforyou] my [/b].".bbcode_to_html.should == "[p]Text and [/b] with a <p> and [quote='Hahah'] a </p> care in sight oh [i=nometaforyou] my [/b]."
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
data/spec/buffer_spec.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BBCoder::Buffer do
|
4
|
+
|
5
|
+
context "#push" do
|
6
|
+
it "should append content onto the current depth without increasing depth" do
|
7
|
+
subject.push("content")
|
8
|
+
subject.push(" + more")
|
9
|
+
subject.pop.should == "content + more"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "#pop" do
|
14
|
+
it "should delete the current depth but not modify the depth" do
|
15
|
+
subject.push("content")
|
16
|
+
subject.pop
|
17
|
+
subject.pop.should == nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "#join" do
|
22
|
+
it "should push remaining tags" do
|
23
|
+
mock(subject).tags.stub!.join {"joined"}
|
24
|
+
mock(subject).push(is_a(String))
|
25
|
+
|
26
|
+
subject.join
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return a string from unopened tags" do
|
30
|
+
subject.tags.push("p")
|
31
|
+
subject.join.should == "[p]"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "#depth" do
|
36
|
+
it "should delegate to tags" do
|
37
|
+
mock(subject).tags.stub!.size {0}
|
38
|
+
subject.depth.should == 0
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BBCoder::BufferTags do
|
4
|
+
|
5
|
+
subject { BBCoder::BufferTags.new(BBCoder::Buffer.new) }
|
6
|
+
|
7
|
+
context "#criteria_met?" do
|
8
|
+
it "should return false when tag does not exist" do
|
9
|
+
subject.criteria_met?(:notatag).should == false
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should return false when open tags does not include parents of tag to be added" do
|
13
|
+
subject.criteria_met?(:li).should == false
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return true when open tags does include parents of tag to be added" do
|
17
|
+
subject.push("ul")
|
18
|
+
subject.criteria_met?(:li).should == true
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return false when current open tag does not have any required parents" do
|
22
|
+
subject.criteria_met?(:p).should == true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "delegation to _internal" do
|
27
|
+
it "#size" do
|
28
|
+
mock(subject)._internal.stub!.size
|
29
|
+
subject.size
|
30
|
+
end
|
31
|
+
|
32
|
+
it "#empty?" do
|
33
|
+
mock(subject)._internal.stub!.empty?
|
34
|
+
subject.empty?
|
35
|
+
end
|
36
|
+
it "#last" do
|
37
|
+
mock(subject)._internal.stub!.last
|
38
|
+
subject.last
|
39
|
+
end
|
40
|
+
|
41
|
+
it "#include?" do
|
42
|
+
mock(subject)._internal.stub!.include?
|
43
|
+
subject.include?(:p)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bbcoder
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- John 'asceth' Long
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-02-10 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rr
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
description: A gem for parsing bbcode that doesn't rely on regular expressions
|
50
|
+
email:
|
51
|
+
- machinist@asceth.com
|
52
|
+
executables: []
|
53
|
+
|
54
|
+
extensions: []
|
55
|
+
|
56
|
+
extra_rdoc_files: []
|
57
|
+
|
58
|
+
files:
|
59
|
+
- .gemtest
|
60
|
+
- .rspec
|
61
|
+
- Gemfile
|
62
|
+
- Gemfile.lock
|
63
|
+
- LICENSE
|
64
|
+
- README.md
|
65
|
+
- Rakefile
|
66
|
+
- bbcoder.gemspec
|
67
|
+
- lib/bbcoder.rb
|
68
|
+
- lib/bbcoder/base.rb
|
69
|
+
- lib/bbcoder/buffer.rb
|
70
|
+
- lib/bbcoder/buffer_tags.rb
|
71
|
+
- lib/bbcoder/configuration.rb
|
72
|
+
- lib/bbcoder/string.rb
|
73
|
+
- lib/bbcoder/tag.rb
|
74
|
+
- lib/bbcoder/version.rb
|
75
|
+
- spec/base_spec.rb
|
76
|
+
- spec/bbcoder_spec.rb
|
77
|
+
- spec/buffer_spec.rb
|
78
|
+
- spec/buffer_tags_spec.rb
|
79
|
+
- spec/spec_helper.rb
|
80
|
+
has_rdoc: true
|
81
|
+
homepage: http://github.com/asceth/bbcoder
|
82
|
+
licenses: []
|
83
|
+
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
hash: 3
|
95
|
+
segments:
|
96
|
+
- 0
|
97
|
+
version: "0"
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
hash: 3
|
104
|
+
segments:
|
105
|
+
- 0
|
106
|
+
version: "0"
|
107
|
+
requirements: []
|
108
|
+
|
109
|
+
rubyforge_project: bbcoder
|
110
|
+
rubygems_version: 1.3.7
|
111
|
+
signing_key:
|
112
|
+
specification_version: 3
|
113
|
+
summary: BBCode parser
|
114
|
+
test_files: []
|
115
|
+
|