th-bbcode 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -104,6 +104,17 @@ are no longer replaced automatically: You need to escape them in your handler
104
104
  callback yourself. Failing to do so might expose your website to XSS
105
105
  vulnerabilities.
106
106
 
107
+ Using another parser or tokenizer:
108
+ ----------------------------------
109
+ Although this bbcode parser gem was primary designed for converting bbcode to
110
+ HTML, it is possible to use another parser or tokenizer while still using the
111
+ same handlers.
112
+
113
+ Using another tokenizer allows you to parse anything as if it were to be
114
+ bbcode. This feature is still in development, but a nice example is my own
115
+ ycode gem. This gem can be found here:
116
+ `https://github.com/tobyhinloopen/y-code`
117
+
107
118
  Todo:
108
119
  -----
109
120
  * An easier way to handle text around bbcode tags to, for example, add smileys
@@ -4,6 +4,7 @@ require 'action_view/helpers/tag_helper'
4
4
  require 'cgi'
5
5
  require "bbcode/version"
6
6
  require "bbcode/tokenizer"
7
+ require "bbcode/abstract_handler"
7
8
  require "bbcode/parser"
8
9
  require "bbcode/handler"
9
10
  require "bbcode/html_handler"
@@ -14,4 +15,31 @@ include ActionView::Helpers::TagHelper
14
15
 
15
16
  module Bbcode
16
17
  String.send :include, Bbcode::Helpers
18
+
19
+ def self.handlers
20
+ @@handlers ||= {}
21
+ end
22
+
23
+ def self.handler(name)
24
+ handlers[name]
25
+ end
26
+
27
+ def self.register_handler(name, handler)
28
+ handlers[name] = handler
29
+ end
30
+
31
+ def self.parsers
32
+ @@parsers ||= {}
33
+ end
34
+
35
+ def self.parser(name)
36
+ parser = parsers[name]
37
+ parser.respond_to?(:call) ? parser.call : parser
38
+ end
39
+
40
+ def self.register_parser(name, parser = nil, &parser_factory)
41
+ parsers[name] = (parser || parser_factory)
42
+ end
43
+
44
+ register_parser(:bbcode){ Parser.new(Tokenizer.new) }
17
45
  end
@@ -0,0 +1,19 @@
1
+ module Bbcode
2
+ class AbstractHandler
3
+ def start_element(tagname, attributes = {}, source = nil); end
4
+ def end_element(tagname, source = nil); end
5
+ def text(text); end
6
+ def interrupt_element(tagname); end
7
+ def continue_element(tagname); end
8
+
9
+ def restart_element(tagname, attributes = {}, source = nil)
10
+ end_element tagname
11
+ start_element tagname, attributes, source
12
+ end
13
+
14
+ def void_element(tagname, attributes = {}, source = nil)
15
+ start_element tagname, attributes, source
16
+ end_element tagname
17
+ end
18
+ end
19
+ end
@@ -4,22 +4,24 @@ module Bbcode
4
4
 
5
5
  attr_reader :locals
6
6
 
7
- def initialize(string, locals = {})
7
+ def initialize(parser, string)
8
+ @parser = parser
8
9
  @string = string
9
10
  end
10
11
 
11
- def to(handler, locals = {})
12
- handler = @@handlers[handler]
13
- raise "Handler #{handler} isn't registered" if handler.blank?
12
+ def to(handler_name, locals = {})
13
+ handler = Bbcode.handler handler_name
14
+ raise "Handler #{handler} isn't registered." if handler.nil?
14
15
  handler.locals = locals.with_indifferent_access
15
- Parser.new(Tokenizer.new).parse @string, handler
16
+ @parser.parse @string, handler
16
17
  result = handler.get_document.content.to_s
17
18
  handler.clear
18
19
  result
19
20
  end
20
21
 
21
22
  def self.register_handler(name, handler)
22
- @@handlers[name] = handler
23
+ puts "WARNING: Bbcode::Base.register_handler is deprecated. Use Bbcode.register_handler instead."
24
+ Bbcode.register_handler(name, handler)
23
25
  end
24
26
  end
25
27
  end
@@ -1,7 +1,7 @@
1
1
  require "bbcode/handler_element"
2
2
 
3
3
  module Bbcode
4
- class Handler
4
+ class Handler < AbstractHandler
5
5
  attr_accessor :element_handlers, :locals
6
6
 
7
7
  def initialize( element_handlers = nil )
@@ -1,7 +1,15 @@
1
1
  module Bbcode
2
2
  module Helpers
3
+ def parse_with(parser)
4
+ Base.new parser, self.to_s
5
+ end
6
+
7
+ def as(parser_name)
8
+ parse_with Bbcode.parser parser_name
9
+ end
10
+
3
11
  def as_bbcode
4
- Base.new self.to_s
12
+ as :bbcode
5
13
  end
6
14
  end
7
15
  end
@@ -1,6 +1,6 @@
1
1
  module Bbcode
2
2
  # Attempts to pair a stream of tokens created by a tokenizer
3
- class Parser
3
+ class Parser < AbstractHandler
4
4
  attr_accessor :tokenizer
5
5
 
6
6
  def initialize( tokenizer = nil )
@@ -14,12 +14,12 @@ module Bbcode
14
14
  end
15
15
 
16
16
  def text( text )
17
- @handler.send :text, text
17
+ @handler.text text
18
18
  end
19
19
 
20
20
  def start_element( tagname, attributes, source )
21
21
  @tags_stack << tagname
22
- @handler.send :start_element, tagname, attributes, source
22
+ @handler.start_element tagname, attributes, source
23
23
  end
24
24
 
25
25
  def end_element( tagname, source )
@@ -29,22 +29,20 @@ module Bbcode
29
29
  @interruption_stack = []
30
30
  while @tags_stack.last != tagname do
31
31
  @interruption_stack << @tags_stack.last
32
- @handler.send :interrupt_element, @tags_stack.pop
32
+ @handler.interrupt_element @tags_stack.pop
33
33
  end
34
34
 
35
- @handler.send :end_element, @tags_stack.pop, source
35
+ @handler.end_element @tags_stack.pop, source
36
36
 
37
37
  while !@interruption_stack.empty? do
38
38
  @tags_stack << @interruption_stack.last
39
- @handler.send :continue_element, @interruption_stack.pop
39
+ @handler.continue_element @interruption_stack.pop
40
40
  end
41
41
  end
42
42
 
43
43
  def parse( document, handler )
44
44
  @handler = handler
45
- @tokenizer.tokenize document do |*args|
46
- self.send *args if [:start_element, :end_element, :text].include?(args.first)
47
- end
45
+ @tokenizer.tokenize document, self
48
46
  end
49
47
  end
50
48
  end
@@ -25,14 +25,14 @@ module Bbcode
25
25
  # Parses the document as BBCode-formatted text and calls block with bbcode
26
26
  # events.
27
27
  #
28
- # The block is called with the following events:
29
- # - :text, text
28
+ # The handler will have the following methods called:
29
+ # - .text text
30
30
  # A text-event with an additional parameter containing the actual text.
31
- # - :start_element, element_name, element_arguments
31
+ # - .start_element element_name, element_arguments
32
32
  # An element-event with 2 additional parameters: The element name as a
33
33
  # symbol and the element attributes as a hash. This events indicate the
34
34
  # start of the element.
35
- # - :end_element, element_name
35
+ # - .end_element element_name
36
36
  # An element-event indicating the end of an element. Optionally, the
37
37
  # element_name is added as a parameter. If no parameter is present, it is
38
38
  # assumed to be the last started element.
@@ -44,12 +44,12 @@ module Bbcode
44
44
  # Also note that :text events are not guaranteed to match the whole text.
45
45
  # In some cases, the text might be separated to multiple :text events, even
46
46
  # though there are no nodes in between.
47
- def tokenize( document, &handler )
47
+ def tokenize(document, handler)
48
48
  while !(match = BBCODE_TAG_PATTERN.match(document)).nil?
49
49
  offset = match.begin(0)
50
50
  elem_source = match[0]
51
51
 
52
- handler.call :text, document[0...offset] unless offset == 0
52
+ handler.text document[0...offset] unless offset == 0
53
53
 
54
54
  elem_is_closing_tag = match[1]=='/'
55
55
  elem_name = (match[2].length > 0 && match[2].to_sym) || nil
@@ -57,18 +57,18 @@ module Bbcode
57
57
 
58
58
  if (elem_is_closing_tag && !elem_attr_string) || (!elem_is_closing_tag && elem_name)
59
59
  if !elem_is_closing_tag
60
- handler.call :start_element, elem_name, parse_attributes_string(elem_attr_string), elem_source
60
+ handler.start_element elem_name, parse_attributes_string(elem_attr_string), elem_source
61
61
  else
62
- handler.call :end_element, elem_name, elem_source
62
+ handler.end_element elem_name, elem_source
63
63
  end
64
64
  else
65
- handler.call :text, elem_source
65
+ handler.text elem_source
66
66
  end
67
67
 
68
68
  document = document[(offset+elem_source.length)..-1]
69
69
  end
70
70
 
71
- handler.call :text, document unless document.length == 0
71
+ handler.text document unless document.length == 0
72
72
  end
73
73
  end
74
74
  end
@@ -1,3 +1,3 @@
1
1
  module Bbcode
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -1,8 +1,4 @@
1
1
  require 'spec_helper.rb'
2
2
 
3
3
  describe Bbcode::Base do
4
- it "should enable a handler to be registered and used" do
5
- Bbcode::Base.register_handler :test, Bbcode::Handler.new
6
- Bbcode::Base.new("test").to(:test).should eql("test")
7
- end
8
4
  end
@@ -19,8 +19,8 @@ quote_handler.register_element_handlers handler.element_handlers.merge({
19
19
  :quote => ->(element){ "[...]" }
20
20
  })
21
21
 
22
- Bbcode::Base.register_handler :html, handler
23
- Bbcode::Base.register_handler :text, Bbcode::Handler.new()
22
+ Bbcode.register_handler :html, handler
23
+ Bbcode.register_handler :text, Bbcode::Handler.new
24
24
 
25
25
  describe Bbcode::Helpers do
26
26
  it "should enable a string to use a registered helper" do
@@ -2,12 +2,9 @@ require 'spec_helper.rb'
2
2
 
3
3
  def get_tokenizer_results(string, strip_source = true)
4
4
  tokenizer = Bbcode::Tokenizer.new
5
- results = []
6
- tokenizer.tokenize string do |*args|
7
- args.pop if strip_source && [:end_element, :start_element].include?(args.first) # pop the source
8
- results.push args
9
- end
10
- results
5
+ handler = DummyHandler.new strip_source
6
+ tokenizer.tokenize string, handler
7
+ handler.stack
11
8
  end
12
9
 
13
10
  describe Bbcode::Tokenizer do
@@ -3,6 +3,18 @@ require 'bundler/setup'
3
3
 
4
4
  require 'bbcode'
5
5
 
6
+ class DummyHandler
7
+ attr_accessor :stack
8
+
9
+ def initialize(strip_source)
10
+ @strip_source = strip_source
11
+ end
12
+
13
+ def method_missing(*args)
14
+ (@stack ||= []) << args.tap{ |args| args.pop if @strip_source && args.first.to_s.end_with?("element") }
15
+ end
16
+ end
17
+
6
18
  RSpec.configure do |config|
7
19
  # some (optional) config here
8
20
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: th-bbcode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-26 00:00:00.000000000Z
12
+ date: 2012-03-14 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70094233269240 !ruby/object:Gem::Requirement
16
+ requirement: &70359577113220 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70094233269240
24
+ version_requirements: *70359577113220
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: activesupport
27
- requirement: &70094233268820 !ruby/object:Gem::Requirement
27
+ requirement: &70359577112800 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70094233268820
35
+ version_requirements: *70359577112800
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: actionpack
38
- requirement: &70094233268400 !ruby/object:Gem::Requirement
38
+ requirement: &70359577112380 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70094233268400
46
+ version_requirements: *70359577112380
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: i18n
49
- requirement: &70094233267980 !ruby/object:Gem::Requirement
49
+ requirement: &70359577111960 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70094233267980
57
+ version_requirements: *70359577111960
58
58
  description: Gem for parsing bbcode-formatted strings to HTML or any other formatting
59
59
  you like (or don't like).
60
60
  email:
@@ -69,6 +69,7 @@ files:
69
69
  - Rakefile
70
70
  - bbcode.gemspec
71
71
  - lib/bbcode.rb
72
+ - lib/bbcode/abstract_handler.rb
72
73
  - lib/bbcode/base.rb
73
74
  - lib/bbcode/element.rb
74
75
  - lib/bbcode/handler.rb