ruby-bbcode 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a10490262219dacfe057278e730b307e8c274c08
4
- data.tar.gz: fc45b4491f2127baffe4d8c73e0a5480e858b9c0
3
+ metadata.gz: 81fc51b37a07ce293879a04f6c2e94d0888a5069
4
+ data.tar.gz: 7f35303b08f5a4f37c311b6aa70babe8e6918d04
5
5
  SHA512:
6
- metadata.gz: e6e07a60e19708e13f1245a4a15874a00b138fb2af64a3d6ae494ea80d4eb90eee84587d3f6d65405b86b1d69100720b67b42af76b4bda81ae676279ae48df50
7
- data.tar.gz: 3873a68c9f3e06de06ff07001507573513b7f219599c8b3d5be460127101eaf4735617d294dbb1cc3146f32d38d7b1378dbaab1f3b0c36093b417c21e2df8475
6
+ metadata.gz: dc09a68f466ee66a7a2591bff3fff64e48db3f2ea2e65f6226979ec5620e9bd0e2e084bfe85162d9c0d9beef5fb0781ffcd4b55d4e5bd5caf06dc9a2d4f836fd
7
+ data.tar.gz: c93e42b5f4b448f9589d105845a116f8d183aa2f66025c09ab07b518de01d85c5c7b0da5c7c92f43fef7233761ccfc5200d8f829331d0415ad9d3415775d4e59
data/CHANGELOG.md CHANGED
@@ -1,4 +1,22 @@
1
+ Upcoming
2
+ --------
3
+
4
+ Version 2.0.0 - 09-Apr-2015
5
+ ---------------------------
6
+
7
+ * Support multiple errors within a text
8
+ * Add parameters to #bbcode_check_validity to add/remove tags
9
+ * Support regular tag parameters (`[tag param=value][/tag]`) instead of 'quick parameters' (`[tag=value][/tag]`)
10
+ * Changed tag description symbols (to become descriptive), **breaks existing custom tag additions!**
11
+ * Add support to show the BBCode annotated with errors (when there are any)
12
+ * Add support to escape token value using :uri_escape.
13
+ * Recognize uppercase tags (issue #27)
14
+ * Support [iframe-API](https://developers.google.com/youtube/iframe_api_reference) for YouTube videos (#18)
15
+ * Support difference between optional and required parameters
16
+ * Add optional parameters to youtube and vimeo tags to specify the dimensions of the video
17
+
1
18
  Version 1.0.1 - 04-Jan-2015
19
+ ---------------------------
2
20
 
3
21
  * Allow any version of activesupport since 3.2.3
4
22
 
data/README.textile CHANGED
@@ -1,16 +1,35 @@
1
1
  h1. Ruby-BBCode
2
2
 
3
- !https://badge.fury.io/rb/ruby-bbcode.svg!:http://badge.fury.io/rb/ruby-bbcode
3
+ !https://badge.fury.io/rb/ruby-bbcode.svg!:http://badge.fury.io/rb/ruby-bbcode !https://travis-ci.org/veger/ruby-bbcode.svg?branch=master!:https://travis-ci.org/veger/ruby-bbcode !https://coveralls.io/repos/veger/ruby-bbcode/badge.svg?branch=master(Coverage Status)!:https://coveralls.io/r/veger/ruby-bbcode?branch=master
4
4
 
5
5
  This gem adds support for "BBCode":http:/www.bbcode.org/ to Ruby. The BBCode is parsed by a parser before converted to HTML, allowing to convert nested BBCode tags in strings to their correct HTML equivalent. The parser also checks whether the BBCode is valid and gives errors for incorrect BBCode texts.
6
+ Additionally, annotations can be added to the BBCode string the showing errors that are present, assuming there are any errors.
6
7
 
7
8
  The parser recognizes all "official tags":http://www.bbcode.org/reference.php and allows to easily extend this set with custom tags.
8
9
 
9
- h2. Example
10
+ See "changelog":CHANGELOG.md for the (recent) notable changes of this gem.
11
+
12
+ h2. Examples
13
+
14
+ <code>bbcode_to_html</code> can be used to convert a BBCode string to HTML:
10
15
 
11
16
  <pre><code>'This is [b]bold[/b] and this is [i]italic[/i].'.bbcode_to_html
12
17
  => 'This is <strong>bold</strong> and this is <em>italic</em>.'</code></pre>
13
18
 
19
+ <code>bbcode_show_errors</code> can be used to convert a BBCode to BBCode annotated with errors (assuming the original BBCode did contain errors):
20
+
21
+ <pre><code>'[img=no_dimensions_here]image.png[/img]'.bbcode_show_errors
22
+ => '<span class=\'bbcode_error\' data-bbcode-errors=\'["The image parameters \'no_dimensions_here\' are incorrect, \'<width>x<height>\' excepted"]\'>[img]</span>image.png[/img]'</code></pre>
23
+
24
+ These HTML attributes containing the JSON representation of the errors can be used to inform the user about the problems.
25
+ The following JavaScript/jQuery example makes use of the "Bootstrap tooltips plugin":http://getbootstrap.com/javascript/#tooltips to show the errors in tooltip popups:
26
+ <pre><code>$(".bbcode_error").tooltip({
27
+ title: function() {
28
+ var errors = JSON.parse($(this).attr('data-bbcode-errors'));
29
+ return errors.join("\n");
30
+ }
31
+ });</code></pre>
32
+
14
33
  h2. Installing
15
34
 
16
35
  Add the following line to the Gemfile of your application:
@@ -34,4 +53,4 @@ Some of the ideas and the tests came from "bb-ruby":http://github.com/cpjolicoeu
34
53
 
35
54
  h2. License
36
55
 
37
- MIT License. See the included "MIT-LICENCE":https://github.com/veger/ruby-bbcode/blob/master/MIT-LICENSE file.
56
+ MIT License. See the included "MIT-LICENCE":MIT-LICENSE file.
data/lib/ruby-bbcode.rb CHANGED
@@ -7,37 +7,42 @@ require 'ruby-bbcode/bbtree'
7
7
 
8
8
  # RubyBBCode adds support for BBCode to Ruby.
9
9
  # The BBCode is parsed by a parser before converted to HTML, allowing to convert nested BBCode tags in strings to their correct HTML equivalent.
10
- # THe used parser also checks whether the BBCode is valid and gives errors for incorrect BBCode texts.
10
+ # The used parser also checks whether the BBCode is valid and gives errors for incorrect BBCode texts.
11
11
  module RubyBBCode
12
12
  include ::RubyBBCode::Tags
13
13
 
14
14
  # This method converts the given text (with BBCode tags) into a HTML representation
15
15
  # The escape_html parameter (default: true) escapes HTML tags that were present in the given text and therefore blocking (mallicious) HTML in the original text
16
16
  # The additional_tags parameter is used to add additional BBCode tags that should be accepted
17
- # The method paramter determines whether the tags parameter needs to be used to blacklist (when set to :disable) or whitelist (when not set to :disable) the list of BBCode tags
17
+ # The method parameter determines whether the tags parameter needs to be used to blacklist (when set to :disable) or whitelist (when not set to :disable) the list of BBCode tags
18
+ # The method raises an exception when the text could not be parsed due to errors
18
19
  def self.to_html(text, escape_html = true, additional_tags = {}, method = :disable, *tags)
19
- text = text.clone
20
-
20
+ parse(text, escape_html, additional_tags, method, *tags)
21
21
  use_tags = determine_applicable_tags(additional_tags, method, *tags)
22
22
 
23
- @tag_sifter = TagSifter.new(text, use_tags, escape_html)
23
+ # We cannot convert to HTML if the BBCode is not valid!
24
+ raise @tag_sifter.errors.join(', ') unless @tag_sifter.valid?
24
25
 
25
- @tag_sifter.process_text
26
-
27
- if @tag_sifter.invalid?
28
- raise @tag_sifter.errors.join(', ') # We cannot convert to HTML if the BBCode is not valid!
29
- else
30
- @tag_sifter.bbtree.to_html(use_tags)
31
- end
26
+ @tag_sifter.bbtree.to_html(use_tags)
27
+ end
32
28
 
29
+ # This method converts the given text (with BBCode tags) into a HTML representation
30
+ # The additional_tags parameter is used to add additional BBCode tags that should be accepted
31
+ # The method parameter determines whether the tags parameter needs to be used to blacklist (when set to :disable) or whitelist (when not set to :disable) the list of BBCode tags
32
+ # The method raises an exception when the text could not be parsed due to errors
33
+ def self.to_bbcode(text, additional_tags = {}, method = :disable, *tags)
34
+ parse(text, true, additional_tags, method, *tags)
35
+ use_tags = determine_applicable_tags(additional_tags, method, *tags)
36
+ @tag_sifter.bbtree.to_bbcode(use_tags)
33
37
  end
34
38
 
35
39
  # Returns true when valid, else returns array with error(s)
36
- def self.validity_check(text, additional_tags = {})
37
- @tag_sifter = TagSifter.new(text, @@tags.merge(additional_tags))
40
+ def self.validity_check(text, additional_tags = {}, method = :disable, *tags)
41
+ use_tags = determine_applicable_tags(additional_tags, method, *tags)
42
+ @tag_sifter = TagSifter.new(text, use_tags)
38
43
 
39
44
  @tag_sifter.process_text
40
- return @tag_sifter.errors if @tag_sifter.invalid?
45
+ return @tag_sifter.errors unless @tag_sifter.valid?
41
46
  true
42
47
  end
43
48
 
@@ -59,34 +64,50 @@ module RubyBBCode
59
64
  use_tags
60
65
  end
61
66
 
62
- def self.parse(text, tags)
63
- @tag_sifter = TagSifter.new(text, tags)
67
+ # This method parses the given text (with BBCode tags) into a BBTree representation
68
+ # The escape_html parameter (default: true) escapes HTML tags that were present in the given text and therefore blocking (mallicious) HTML in the original text
69
+ # The additional_tags parameter is used to add additional BBCode tags that should be accepted
70
+ # The method parameter determines whether the tags parameter needs to be used to blacklist (when set to :disable) or whitelist (when not set to :disable) the list of BBCode tags
71
+ # The method raises an exception when the text could not be parsed due to errors
72
+ def self.parse(text, escape_html = true, additional_tags = {}, method = :disable, *tags)
73
+ text = text.clone
74
+ use_tags = determine_applicable_tags(additional_tags, method, *tags)
64
75
 
76
+ @tag_sifter = TagSifter.new(text, use_tags, escape_html)
65
77
  @tag_sifter.process_text
66
-
67
- if @tag_sifter.invalid?
68
- @tag_sifter.errors
69
- else
70
- true
71
- end
72
-
73
78
  end
74
-
75
79
  end
76
80
 
77
81
  String.class_eval do
78
82
  # Convert a string with BBCode markup into its corresponding HTML markup
83
+ # The escape_html parameter (default: true) escapes HTML tags that were present in the given text and therefore blocking (mallicious) HTML in the original text
84
+ # The additional_tags parameter is used to add additional BBCode tags that should be accepted
85
+ # The method parameter determines whether the tags parameter needs to be used to blacklist (when set to :disable) or whitelist (when not set to :disable) the list of BBCode tags
86
+ # The method raises an exception when the text could not be parsed due to errors
79
87
  def bbcode_to_html(escape_html = true, additional_tags = {}, method = :disable, *tags)
80
88
  RubyBBCode.to_html(self, escape_html, additional_tags, method, *tags)
81
89
  end
82
90
 
83
91
  # Replace the BBCode content of a string with its corresponding HTML markup
92
+ # The escape_html parameter (default: true) escapes HTML tags that were present in the given text and therefore blocking (mallicious) HTML in the original text
93
+ # The additional_tags parameter is used to add additional BBCode tags that should be accepted
94
+ # The method parameter determines whether the tags parameter needs to be used to blacklist (when set to :disable) or whitelist (when not set to :disable) the list of BBCode tags
95
+ # The method raises an exception when the text could not be parsed due to errors
84
96
  def bbcode_to_html!(escape_html = true, additional_tags = {}, method = :disable, *tags)
85
97
  self.replace(RubyBBCode.to_html(self, escape_html, additional_tags, method, *tags))
86
98
  end
87
99
 
100
+ # Convert a string with BBCode markup into its corresponding HTML markup
101
+ # Note that the returned bbocde, might differ than the original bbcode, as the original gets parsed and molded into something workable. For example, by adding closing tags (when they are optional), or by converting generic tags into specific ones.
102
+ def bbcode_show_errors(additional_tags = {}, method = :disable, *tags)
103
+ RubyBBCode.to_bbcode(self, additional_tags, method, *tags)
104
+ end
105
+
88
106
  # Check if string contains valid BBCode. Returns true when valid, else returns array with error(s)
89
- def bbcode_check_validity
90
- RubyBBCode.validity_check(self)
107
+ # The additional_tags parameter is used to add additional BBCode tags that should be accepted
108
+ # The method parameter determines whether the tags parameter needs to be used to blacklist (when set to :disable) or whitelist (when not set to :disable) the list of BBCode tags
109
+ # The method raises an exception when the text could not be parsed due to errors
110
+ def bbcode_check_validity(additional_tags = {}, method = :disable, *tags)
111
+ RubyBBCode.validity_check(self, additional_tags, method, *tags)
91
112
  end
92
113
  end
@@ -3,64 +3,50 @@ module RubyBBCode
3
3
  #
4
4
  # As you parse a string of text, say:
5
5
  # "[b]I'm bold and the next word is [i]ITALIC[/i][b]"
6
- # ...you build up a tree of nodes (@bbtree). The above string converts to 4 nodes when the parse has completed.
6
+ # ...you build up a tree of nodes (@bbtree). The above string is represented by 4 nodes when parsing has completed.
7
7
  # * Node 1) An opening tag node representing "[b]"
8
8
  # * Node 2) A text node representing "I'm bold and the next word is "
9
9
  # * Node 3) An opening tag node representing "[i]"
10
10
  # * Node 4) A text node representing "ITALIC"
11
11
  #
12
- # The closing of the nodes seems to be implied which is fine by me --less to keep track of.
13
- #
14
12
  class BBTree
15
13
  attr_accessor :current_node, :tags_list
16
-
17
- def initialize(hash = { :nodes => TagCollection.new }, dictionary)
14
+
15
+ def initialize(hash = { :nodes => TagCollection.new })
18
16
  @bbtree = hash
19
17
  @current_node = TagNode.new(@bbtree)
20
18
  @tags_list = []
21
- @dictionary = dictionary
22
- end
23
-
24
- def [](key)
25
- @bbtree[key]
26
19
  end
27
-
28
- def []=(key, value)
29
- @bbtree[key] = value
30
- end
31
-
20
+
32
21
  def nodes
33
22
  @bbtree[:nodes]
34
23
  end
35
- alias :children :nodes # needed due to the similarities between BBTree[:nodes] and TagNode[:nodes]... they're walked through in debugging.rb right now
36
-
37
- def type
38
- :bbtree
39
- end
40
-
24
+
41
25
  def within_open_tag?
42
26
  @tags_list.length > 0
43
27
  end
44
28
  alias :expecting_a_closing_tag? :within_open_tag? # just giving this method multiple names for semantical purposes
45
-
29
+
30
+ # Returns the parent tag, if suitable/available
46
31
  def parent_tag
47
- return nil if !within_open_tag?
48
- @tags_list.last.to_sym
32
+ return nil unless within_open_tag?
33
+ @tags_list.last
49
34
  end
50
-
35
+
36
+ # Return true if the parent tag only allows certain child tags
51
37
  def parent_has_constraints_on_children?
52
- @dictionary[parent_tag][:only_allow] != nil
38
+ parent_tag[:definition][:only_allow] != nil
53
39
  end
54
-
40
+
55
41
  # Advance to next level (the node we just added)
56
42
  def escalate_bbtree(element)
57
- @tags_list.push element[:tag]
58
43
  @current_node = TagNode.new(element)
44
+ @tags_list.push @current_node
59
45
  end
60
-
46
+
61
47
  # Step down the bbtree a notch because we've reached a closing tag
62
48
  def retrogress_bbtree
63
- @tags_list.pop # remove latest tag in tags_list since it's closed now...
49
+ @tags_list.pop # remove latest tag in tags_list since it's closed now...
64
50
  # The parsed data manifests in @bbtree.current_node.children << TagNode.new(element) which I think is more confusing than needed
65
51
 
66
52
  if within_open_tag?
@@ -69,26 +55,19 @@ module RubyBBCode
69
55
  else # If we're still at the root of the BBTree or have returned back to the root via encountring closing tags...
70
56
  @current_node = TagNode.new({:nodes => self.nodes}) # Note: just passing in self works too...
71
57
  end
72
-
73
- # OKOKOK!
74
- # Since @bbtree = @current_node, if we ever set @current_node to something, we're actually changing @bbtree...
75
- # therefore... my brain is now numb
76
58
  end
77
-
78
- def redefine_parent_tag_as_text
79
- @tags_list.pop
80
- @current_node[:is_tag] = false
81
- @current_node[:closing_tag] = false
82
- @current_node.element[:text] = "[#{@current_node[:tag].to_s}]"
83
- end
84
-
59
+
60
+ # Create a new node and adds it to the current node as a child node
85
61
  def build_up_new_tag(element)
86
62
  @current_node.children << TagNode.new(element)
87
63
  end
88
-
64
+
89
65
  def to_html(tags = {})
90
66
  self.nodes.to_html(tags)
91
67
  end
92
-
68
+
69
+ def to_bbcode(tags = {})
70
+ self.nodes.to_bbcode(tags)
71
+ end
93
72
  end
94
- end
73
+ end
@@ -1,99 +1,49 @@
1
+ require 'ruby-bbcode/templates/html_template'
2
+ require 'ruby-bbcode/templates/bbcode_errors_template'
3
+
1
4
  module RubyBBCode
2
- # This class holds TagNode instances and helps build them into html when the time comes.
3
- #
4
- # It is really just a simple array, with the addition of the #to_html method
5
+ # This class holds TagNode instances and helps converting them into code (using the provided template) when the time comes.
5
6
  class TagCollection < Array
6
-
7
- # This method is vulnerable to stack-level-too-deep scenarios where >=1,200 tags are being parsed.
7
+ # Convert nodes to HTML
8
+ def to_html(tags)
9
+ to_code(tags, RubyBBCode::Templates::HtmlTemplate)
10
+ end
11
+
12
+ # Convert nodes to BBCode (with error information)
13
+ def to_bbcode(tags)
14
+ to_code(tags, RubyBBCode::Templates::BBCodeErrorsTemplate)
15
+ end
16
+
17
+ # This method is vulnerable to stack-level-too-deep scenarios where >=1,200 tags are being parsed.
8
18
  # But that scenario can be mitigated by splitting up the tags. bbtree = { :nodes => [900tags, 1000tags] }, the work
9
19
  # for that bbtree can be split up into two passes, do the each node one at a time. I'm not coding that though, it's pointless, just a thought though
10
- def to_html(tags)
20
+ def to_code(tags, template)
11
21
  html_string = ""
12
22
  self.each do |node|
13
23
  if node.type == :tag
14
- t = HtmlTemplate.new node
15
-
24
+ t = template.new node
25
+
16
26
  t.inlay_between_text!
17
-
18
- if node.allow_tag_param? and node.param_set?
19
- t.inlay_inline_params!
20
- elsif node.allow_tag_param? and node.param_not_set?
27
+
28
+ if node.allow_params?
29
+ t.inlay_params!
21
30
  t.remove_unused_tokens!
22
31
  end
23
-
24
- html_string << t.opening_html
25
-
32
+
33
+ html_string << t.opening_part
34
+
26
35
  # invoke "recursive" call if this node contains child nodes
27
- html_string << node.children.to_html(tags) if node.has_children? # FIXME: Don't use recursion, it can lead to stack-level-too-deep errors for large volumes?
28
-
29
- t.inlay_closing_html!
30
-
31
- html_string << t.closing_html
36
+ html_string << node.children.to_code(tags, template) if node.has_children? # FIXME: Don't use recursion, it can lead to stack-level-too-deep errors for large volumes?
37
+
38
+ t.inlay_closing_part!
39
+
40
+ html_string << t.closing_part
32
41
  elsif node.type == :text
33
- html_string << node[:text] unless node[:text].nil?
42
+ html_string << template.convert_text(node)
34
43
  end
35
44
  end
36
-
45
+
37
46
  html_string
38
47
  end
39
-
40
-
41
-
42
- # This class is designed to help us build up the HTML data. It starts out as a template such as...
43
- # @opening_html = '<a href="%url%">%between%'
44
- # @closing_html = '</a>'
45
- # and then slowly turns into...
46
- # @opening_html = '<a href="http://www.blah.com">cool beans'
47
- # @closing_html = '</a>'
48
- # TODO: Think about creating a separate file for this or something... maybe look into folder structures cause this project
49
- # got huge when I showed up.
50
- class HtmlTemplate
51
- attr_accessor :opening_html, :closing_html
52
-
53
- def initialize(node)
54
- @node = node
55
- @tag_definition = node.definition # tag_definition
56
- @opening_html = node.definition[:html_open].dup
57
- @closing_html = node.definition[:html_close].dup
58
- end
59
-
60
- def inlay_between_text!
61
- @opening_html.gsub!('%between%',@node[:between]) if between_text_goes_into_html_output_as_param? # set the between text to where it goes if required to do so...
62
- end
63
-
64
- def inlay_inline_params!
65
- # Get list of paramaters to feed
66
- match_array = @node[:params][:tag_param].scan(@tag_definition[:tag_param])[0]
67
-
68
- # for each parameter to feed
69
- match_array.each.with_index do |match, i|
70
- if i < @tag_definition[:tag_param_tokens].length
71
-
72
- # Substitute the %param% keyword for the appropriate data specified
73
- @opening_html.gsub!("%#{@tag_definition[:tag_param_tokens][i][:token].to_s}%",
74
- @tag_definition[:tag_param_tokens][i][:prefix].to_s +
75
- match +
76
- @tag_definition[:tag_param_tokens][i][:postfix].to_s)
77
- end
78
- end
79
- end
80
-
81
- def inlay_closing_html!
82
- @closing_html.gsub!('%between%',@node[:between]) if @tag_definition[:require_between]
83
- end
84
-
85
- def remove_unused_tokens!
86
- @tag_definition[:tag_param_tokens].each do |token|
87
- @opening_html.gsub!("%#{token[:token]}%", '')
88
- end
89
- end
90
-
91
- private
92
-
93
- def between_text_goes_into_html_output_as_param?
94
- @tag_definition[:require_between]
95
- end
96
- end
97
-
98
- end
48
+ end
99
49
  end