diff --git a/Rakefile b/Rakefile
index 7b0672d..c662a0f 100644
--- a/Rakefile
+++ b/Rakefile
@@ -9,7 +9,7 @@ begin
rescue LoadError
require 'rdoc/rdoc'
require 'rake/rdoctask'
- require 'rdoc/task'
+ require 'rdoc/task'
RDoc::Task = Rake::RDocTask
end
diff --git a/lib/ruby-bbcode-to-md.rb b/lib/ruby-bbcode-to-md.rb
index 376021a..ea5590e 100644
--- a/lib/ruby-bbcode-to-md.rb
+++ b/lib/ruby-bbcode-to-md.rb
@@ -27,7 +27,7 @@ def self.validation_enabled
# This method converts the given text (with BBCode tags) into a HTML representation
# 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
# The additional_tags parameter is used to add additional BBCode tags that should be accepted
- # 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
+ # 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
def self.to_html(text, escape_html = true, additional_tags = {}, method = :disable, *tags)
text = text.clone
diff --git a/lib/ruby-bbcode-to-md/bbtree.rb b/lib/ruby-bbcode-to-md/bbtree.rb
index 93c8921..eef52e3 100644
--- a/lib/ruby-bbcode-to-md/bbtree.rb
+++ b/lib/ruby-bbcode-to-md/bbtree.rb
@@ -17,6 +17,7 @@ def initialize(hash = { :nodes => TagCollection.new }, dictionary)
@bbtree = hash
@current_node = TagNode.new(@bbtree)
@tags_list = []
+ @nodes_list = []
@dictionary = dictionary
end
@@ -55,6 +56,7 @@ def parent_has_constraints_on_children?
def escalate_bbtree(element)
element[:parent_tag] = parent_tag
@tags_list.push element[:tag]
+ @nodes_list.push @current_node
@current_node = TagNode.new(element)
end
@@ -63,12 +65,7 @@ def retrogress_bbtree
@tags_list.pop # remove latest tag in tags_list since it's closed now...
# The parsed data manifests in @bbtree.current_node.children << TagNode.new(element) which I think is more confusing than needed
- if within_open_tag?
- # Set the current node to be the node we've just parsed over which is infact within another node??...
- @current_node = TagNode.new(self.nodes.last)
- else # If we're still at the root of the BBTree or have returned back to the root via encountring closing tags...
- @current_node = TagNode.new({:nodes => self.nodes})
- end
+ @current_node = @nodes_list.pop
# OKOKOK!
# Since @bbtree = @current_node, if we ever set @current_node to something, we're actually changing @bbtree...
@@ -91,4 +88,4 @@ def to_html(tags = {})
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/ruby-bbcode-to-md/debugging.rb b/lib/ruby-bbcode-to-md/debugging.rb
index f09639c..33bad57 100644
--- a/lib/ruby-bbcode-to-md/debugging.rb
+++ b/lib/ruby-bbcode-to-md/debugging.rb
@@ -1,12 +1,12 @@
module RubyBBCode
def self.log(string, clear_file = true)
clear_log_file_at_beginning_of_execution clear_file
-
+
File.open('/tmp/ruby-bbcode.log', 'a') do |f|
f.puts string
end
end
-
+
def self.clear_log_file_at_beginning_of_execution(clear_file)
return if !clear_file
if defined?(@@cleared_file).nil?
@@ -16,16 +16,16 @@ def self.clear_log_file_at_beginning_of_execution(clear_file)
end
end
end
-
-
+
+
# This module can be included in the BBTree and TagNode to give them debugging features
module DebugBBTree
# For Debugging/ visualization purposes.
- # This can be used to render the #nodes array in a pretty manor, showing the hirarchy.
+ # This can be used to render the #nodes array in a pretty manor, showing the hierarchy.
def to_v
tree = self
visual_string = ''
-
+
walk_tree(tree) do |node, depth|
indentation = ' ' * depth
case node[:is_tag]
@@ -35,11 +35,11 @@ def to_v
visual_string += "#{indentation}\"#{node[:text]}\"\n"
end
end
-
+
visual_string
end
-
-
+
+
# this blocky method counts how many children are
# in the TagNode.children, recursively walking the tree
def count_child_nodes(hash = self)
@@ -50,13 +50,13 @@ def count_child_nodes(hash = self)
count
end
- # For BBTree, teh to_s method shows the count of the children plus a graphical
- # depiction of the tree, and the relation of the nodes.
- # For TagNodes, the root-most tag is displayed, and the children are counted.
+ # For BBTree, the to_s method shows the count of the children plus a graphical
+ # depiction of the tree, and the relation of the nodes.
+ # For TagNodes, the root-most tag is displayed, and the children are counted.
def to_s
object_identifier = "#<#{self.class.to_s}:0x#{'%x' % (self.object_id << 1)}\n"
close_object = ">\n"
-
+
case self
when RubyBBCode::BBTree
object_identifier + "Children: #{count_child_nodes}\n" + self.to_v + close_object
@@ -68,26 +68,26 @@ def to_s
end
end
end
-
+
private
-
- # This function is used by to_v and anything else that needs to iterate through the
+
+ # This function is used by to_v and anything else that needs to iterate through the
# @bbtree
def walk_tree(tree, depth = -1, &blk)
return enum_for(:walk_tree) unless blk # ignore me for now, I'm a convention for being versatile
-
+
# Perform the block action specified at top level!!!
yield tree, depth unless depth == -1
-
+
# next if we're a text node
return if tree.type == :text
-
+
# Enter into recursion (including block action) for each child node in this node
tree.children.each do |node|
walk_tree(node, depth + 1, &blk)
end
end
-
+
end
-
-end
\ No newline at end of file
+
+end
diff --git a/lib/ruby-bbcode-to-md/tag_collection.rb b/lib/ruby-bbcode-to-md/tag_collection.rb
index 9e92e72..4fa7a44 100644
--- a/lib/ruby-bbcode-to-md/tag_collection.rb
+++ b/lib/ruby-bbcode-to-md/tag_collection.rb
@@ -9,6 +9,14 @@ def to_html(tags)
# let child node render:
children_html = node.has_children? ? node.children.to_html(tags) : nil
+ if children_html
+ if node.definition[:newlines] == :to_br
+ children_html.gsub!(/\n/, "
")
+ elsif node.definition[:paragraphs].nil? || node.definition[:paragraphs] == :to_br
+ children_html.gsub!(/\n\s*\n/, "\n
")
+ end
+ end
+
t = HtmlTemplate.new node
t.inlay_between_text!(children_html)
@@ -118,4 +126,4 @@ def between_text_goes_into_html_output_as_param?
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/ruby-bbcode-to-md/tag_node.rb b/lib/ruby-bbcode-to-md/tag_node.rb
index 40ed60f..67614c9 100644
--- a/lib/ruby-bbcode-to-md/tag_node.rb
+++ b/lib/ruby-bbcode-to-md/tag_node.rb
@@ -64,4 +64,4 @@ def tag_param=(param)
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/ruby-bbcode-to-md/tag_sifter.rb b/lib/ruby-bbcode-to-md/tag_sifter.rb
index 8c32b42..9b9a8b7 100644
--- a/lib/ruby-bbcode-to-md/tag_sifter.rb
+++ b/lib/ruby-bbcode-to-md/tag_sifter.rb
@@ -25,6 +25,7 @@ def process_text
@ti.handle_unregistered_tags_as_text # if the tag isn't in the @dictionary list, then treat it as text
handle_closing_tags_that_are_multi_as_text_if_it_doesnt_match_the_latest_opener_tag_on_the_stack
+ handle_tags_that_are_plain_as_text_if_it_doesnt_match_the_latest_opener_tag_on_the_stack
return if !valid_element?
@@ -99,6 +100,18 @@ def handle_closing_tags_that_are_multi_as_text_if_it_doesnt_match_the_latest_ope
end
+ def handle_tags_that_are_plain_as_text_if_it_doesnt_match_the_latest_opener_tag_on_the_stack
+ if @ti.element_is_tag?
+ return if @bbtree.current_node[:definition].nil?
+ if parent_tag != @ti[:tag].to_sym and @bbtree.current_node[:definition][:plain_tag]
+ @ti[:is_tag] = false
+ @ti[:closing_tag] = false
+ @ti[:text] = @ti.tag_data[:complete_match]
+ end
+ end
+
+ end
+
private
diff --git a/lib/tags/tags.rb b/lib/tags/tags.rb
index a3551c4..a32620a 100644
--- a/lib/tags/tags.rb
+++ b/lib/tags/tags.rb
@@ -1,7 +1,7 @@
module RubyBBCode
module Tags
# tagname => tag, HTML open tag, HTML close tag, description, example
- # All of these entrys are represented as @dictionary in the classes (or as the variable tags)
+ # All of these entries are represented as @dictionary in the classes (or as the variable tags)
# A single item from this file (eg the :b entry) is refered to as a @definition
@@tags = {
:b => {
@@ -16,6 +16,15 @@ module Tags
:html_open => '', :html_close => '',
:description => 'Underline text',
:example => 'This is [u]underlined[/u].'},
+ :s => {
+ :html_open => '~~', :html_close => '~~',
+ :description => 'Strike-through text',
+ :example => 'This is strike-through text.'},
+ :code => {
+ :html_open => "\n```\n", :html_close => "\n```\n",
+ :description => 'Code block',
+ :example => '[code]code[/code].',
+ :plain_tag => true},
:center => {
:html_open => '', :html_close => '',
:description => 'Center a text',
@@ -24,12 +33,14 @@ module Tags
:html_open => "\n", :html_close => "\n",
:description => 'Unordered list',
:example => '[ul][li]List item[/li][li]Another list item[/li][/ul].',
- :only_allow => [ :li ]},
+ :only_allow => [ :li ],
+ :paragraphs => :allow},
:ol => {
:html_open => "\n", :html_close => "\n",
:description => 'Ordered list',
:example => '[ol][li]List item[/li][li]Another list item[/li][/ol].',
- :only_allow => [ :li ]},
+ :only_allow => [ :li ],
+ :paragraphs => :allow},
:li => {
:html_open => {
:ul => ' - ',
@@ -61,20 +72,21 @@ module Tags
:tag_param => /(.*)/,
:tag_param_tokens => [{:token => :href}]},
:quote => {
- :first_html_open => "\n", :last_html_close => "\n",
- :html_open => "[quote%author%]", :html_close => "[/quote]\n",
+ :html_open => "\n[quote%author%]\n", :html_close => "\n[/quote]\n",
:description => 'Quote another person',
:example => '[quote]BBCode is great[/quote]',
:allow_tag_param => true, :allow_tag_param_between => false,
:tag_param => /(.*)/,
- :tag_param_tokens => [{:token => :author, :prefix => '=', :postfix => ""}]},
+ :tag_param_tokens => [{:token => :author, :prefix => '=', :postfix => ""}],
+ :paragraphs => :allow},
:size => {
:html_open => '[size=%size%]', :html_close => '[/size]',
:description => 'Change the size of the text',
:example => '[size=32]This is 32px[/size]',
:allow_tag_param => true, :allow_tag_param_between => false,
:tag_param => /(\d*)/,
- :tag_param_tokens => [{:token => :size}]},
+ :tag_param_tokens => [{:token => :size}],
+ :paragraphs => :allow},
:color => {
:html_open => '', :html_close => '',
:description => 'Change the color of the text',
diff --git a/test/fluxbb_test.rb b/test/fluxbb_test.rb
new file mode 100644
index 0000000..59db167
--- /dev/null
+++ b/test/fluxbb_test.rb
@@ -0,0 +1,44 @@
+require_relative 'test_helper'
+
+class FluxbbTest < MiniTest::Unit::TestCase
+ def fluxbb_tags
+ return {
+ img: RubyBBCode::Tags.tag_list[:img].merge(
+ :html_open => '
',
+ :html_close => '',
+ :example => '[img=my alt text]http://www.google.com/intl/en_ALL/images/logo.gif[/img]',
+ :tag_param => /(.*)/,
+ :tag_param_tokens => [{:token => :alt_text, :prefix => ' alt="', :postfix => '"'}],
+ :tag_param_description => 'The img bbcode takes alt text as a parameter'
+ ),
+ :h => {
+ :html_open => "\n### ", :html_close => "\n",
+ :newlines => :to_br,
+ :description => 'Make a heading',
+ :example => '[h]My Heading[/h].'}
+ }
+ end
+
+ def test_heading
+ assert_equal "\n### My Heading\n", "[h]My Heading[/h]".bbcode_to_md(false, fluxbb_tags)
+ end
+
+ def test_heading_on_two_lines
+ assert_equal "\n### My Heading
on two lines\n", "[h]My Heading\non two lines[/h]".bbcode_to_md(false, fluxbb_tags)
+ end
+
+ def test_image_with_alt_text
+ assert_equal '
',
+ '[img=FluxBB allows alt text]http://www.ruby-lang.org/images/header-ruby-logo.png[/img]'.bbcode_to_md(false, fluxbb_tags)
+ end
+
+ def test_image_without_alt_text
+ assert_equal '
',
+ '[img]http://www.ruby-lang.org/images/header-ruby-logo.png[/img]'.bbcode_to_md(false, fluxbb_tags)
+ end
+
+ def test_ignored_attempt_to_pass_width_height
+ assert_equal '
',
+ '[img=100x200]http://www.ruby-lang.org/images/header-ruby-logo.png[/img]'.bbcode_to_md(false, fluxbb_tags)
+ end
+end
diff --git a/test/ruby_bbcode_test.rb b/test/ruby_bbcode_test.rb
index 24f05d0..d8dc916 100644
--- a/test/ruby_bbcode_test.rb
+++ b/test/ruby_bbcode_test.rb
@@ -9,7 +9,7 @@ def test_multiline
def test_strong
assert_equal '**simple**', '[b]simple[/b]'.bbcode_to_md
- assert_equal "**line 1\nline 2**", "**line 1\nline 2**".bbcode_to_md
+ assert_equal "**line 1\nline 2**", "[b]line 1\nline 2[/b]".bbcode_to_md
end
def test_em
@@ -17,11 +17,20 @@ def test_em
assert_equal "*line 1\nline 2*", "[i]line 1\nline 2[/i]".bbcode_to_md
end
+ def test_paragraph_breaking_up_markdown
+ assert_equal "**paragraph 1\n
paragraph 2**", "[b]paragraph 1\n\nparagraph 2[/b]".bbcode_to_md
+ assert_equal "*paragraph 1\n
paragraph 2*", "[i]paragraph 1\n\nparagraph 2[/i]".bbcode_to_md
+ end
+
def test_u
assert_equal 'simple', '[u]simple[/u]'.bbcode_to_md
assert_equal "line 1\nline 2", "[u]line 1\nline 2[/u]".bbcode_to_md
end
+ def test_s
+ assert_equal '~~simple~~', '[s]simple[/s]'.bbcode_to_md
+ end
+
def test_size
assert_equal '[size=32]32px Text[/size]', '[size=32]32px Text[/size]'.bbcode_to_md
end
@@ -34,6 +43,14 @@ def test_color
def test_center
assert_equal 'centered', '[center]centered[/center]'.bbcode_to_md
end
+
+ def test_code
+ assert_equal "\n```\ncode\n```\n", '[code]code[/code]'.bbcode_to_md
+ assert_equal "\n```\ncode\n```\n", '[code=javascript]code[/code]'.bbcode_to_md
+ assert_equal "\n```\nSome [b]bbcode[/b] :-)\n```\n", '[code]Some [b]bbcode[/b] :-)[/code]'.bbcode_to_md
+ assert_equal "\n```\nSome <b>html</b>\n```\n", '[code]Some html[/code]'.bbcode_to_md
+ assert_equal "\n```\nSome html\n```\n", '[code]Some html[/code]'.bbcode_to_md(false)
+ end
def test_ordered_list
assert_equal "\n 1. item 1\n 1. item 2\n\n", '[ol][li]item 1[/li][li]item 2[/li][/ol]'.bbcode_to_md
@@ -55,13 +72,15 @@ def test_whitespace_in_only_allowed_tags
end
def test_quote
- assert_equal "\n[quote]quoting[/quote]\n\n", '[quote]quoting[/quote]'.bbcode_to_md
- assert_equal "\n[quote=someone]quoting[/quote]\n\n", '[quote=someone]quoting[/quote]'.bbcode_to_md
+ assert_equal "\n[quote]\nquoting\n[/quote]\n", '[quote]quoting[/quote]'.bbcode_to_md
+ assert_equal "\n[quote=someone]\nquoting\n[/quote]\n", '[quote=someone]quoting[/quote]'.bbcode_to_md
end
def test_nested_quotes
- assert_equal "\n[quote=Kitten]\n[quote=creatiu]f1[/quote]\n\nf2[/quote]\n\n",
+ assert_equal "\n[quote=Kitten]\n\n[quote=creatiu]\nf1\n[/quote]\nf2\n[/quote]\n",
'[quote=Kitten][quote=creatiu]f1[/quote]f2[/quote]'.bbcode_to_md
+ assert_equal "A\n[quote]\nB\n[quote]\nC\n[quote]\nD\n[/quote]\nE\n[/quote]\nF\n[/quote]\nG",
+ 'A[quote]B[quote]C[quote]D[/quote]E[/quote]F[/quote]G'.bbcode_to_md
end
def test_link
@@ -138,7 +157,7 @@ def test_addition_of_tags
end
def test_multiple_tag_test
- assert_equal "**bold***italic*underline\n[quote]quote[/quote]\n\n[link](https://test.com)",
+ assert_equal "**bold***italic*underline\n[quote]\nquote\n[/quote]\n[link](https://test.com)",
"[b]bold[/b][i]italic[/i][u]underline[/u][quote]quote[/quote][url=https://test.com]link[/url]".bbcode_to_md
end
@@ -157,15 +176,15 @@ def test_different_start_and_ending_tags
# TODO: This stack level problem should be validated during the validations
def test_stack_level_too_deep
num = 2300 # increase this number if the test starts failing. It's very near the tipping point
- openers = "[s]hi i'm" * num
- closers = "[/s]" * num
+ openers = "[x]hi i'm" * num
+ closers = "[/x]" * num
assert_raises( RuntimeError ) do
(openers+closers).bbcode_to_md
end
end
- def test_mulit_tag
+ def test_multi_tag
input1 = "[media]https://www.youtube.com/watch?v=cSohjlYQI2A[/media]"
input2 = "[media]http://vimeo.com/46141955[/media]"
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 1773bd6..1ca1f19 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -1,7 +1,7 @@
require 'ruby-bbcode-to-md'
require 'minitest/autorun'
-# This hack allows us to make all the private methods of a class public.
+# This hack allows us to make all the private methods of a class public.
class Class
def publicize_methods
saved_private_instance_methods = self.private_instance_methods
diff --git a/test/unit/debugging_test.rb b/test/unit/debugging_test.rb
index ba38a1f..f9a8eb8 100644
--- a/test/unit/debugging_test.rb
+++ b/test/unit/debugging_test.rb
@@ -2,7 +2,7 @@
class RubyBbcodeTest < MiniTest::Unit::TestCase
include ::RubyBBCode::Tags
-
+
def test_bbtree_to_v
text = "[i][b]a[/b][b]a[/b][b]a[/b][b]a[/b]item 1[/i][i]item 2[/i]"
visual = <