From 9c7c72390270f5146325d11a8574724cb492b921 Mon Sep 17 00:00:00 2001 From: Harry Wood Date: Fri, 4 Nov 2022 01:36:18 +0000 Subject: [PATCH 01/14] Minor linting fixes tabs and whitespace Swap out tab characters for spaces to give consistent indenting. Drop trailing whitespace characters at the ends of lines. Add a consitent trailing newline on every file. Done using rubocop: `rubocop --only Layout/IndentationStyle --autocorrect` `rubocop --only Layout/TrailingWhitespace --autocorrect` `rubocop --only Layout/TrailingEmptyLines --autocorrect` --- Rakefile | 2 +- lib/ruby-bbcode-to-md/bbtree.rb | 2 +- lib/ruby-bbcode-to-md/debugging.rb | 42 +++++++++++----------- lib/ruby-bbcode-to-md/tag_collection.rb | 2 +- lib/ruby-bbcode-to-md/tag_node.rb | 2 +- test/test_helper.rb | 2 +- test/unit/debugging_test.rb | 22 ++++++------ test/unit/tag_sifter_test.rb | 48 ++++++++++++------------- 8 files changed, 61 insertions(+), 61 deletions(-) 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/bbtree.rb b/lib/ruby-bbcode-to-md/bbtree.rb index 93c8921..2bdc963 100644 --- a/lib/ruby-bbcode-to-md/bbtree.rb +++ b/lib/ruby-bbcode-to-md/bbtree.rb @@ -91,4 +91,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..0568aac 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 hirarchy. 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) @@ -51,12 +51,12 @@ def count_child_nodes(hash = self) 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. + # 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..490a91e 100644 --- a/lib/ruby-bbcode-to-md/tag_collection.rb +++ b/lib/ruby-bbcode-to-md/tag_collection.rb @@ -118,4 +118,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/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 = < Date: Fri, 4 Nov 2022 02:14:09 +0000 Subject: [PATCH 02/14] Fix typos --- lib/ruby-bbcode-to-md.rb | 2 +- lib/ruby-bbcode-to-md/debugging.rb | 4 ++-- lib/tags/tags.rb | 2 +- test/ruby_bbcode_test.rb | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) 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/debugging.rb b/lib/ruby-bbcode-to-md/debugging.rb index 0568aac..33bad57 100644 --- a/lib/ruby-bbcode-to-md/debugging.rb +++ b/lib/ruby-bbcode-to-md/debugging.rb @@ -21,7 +21,7 @@ def self.clear_log_file_at_beginning_of_execution(clear_file) # 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 = '' @@ -50,7 +50,7 @@ def count_child_nodes(hash = self) count end - # For BBTree, teh to_s method shows the count of the children plus a graphical + # 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 diff --git a/lib/tags/tags.rb b/lib/tags/tags.rb index a3551c4..2471315 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 => { diff --git a/test/ruby_bbcode_test.rb b/test/ruby_bbcode_test.rb index 24f05d0..72e8d67 100644 --- a/test/ruby_bbcode_test.rb +++ b/test/ruby_bbcode_test.rb @@ -165,7 +165,7 @@ def test_stack_level_too_deep 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]" From 85681a45763e732425d5e30a1304e9468d043f80 Mon Sep 17 00:00:00 2001 From: Harry Wood Date: Tue, 8 Nov 2022 03:54:47 +0000 Subject: [PATCH 03/14] Fix the b tag with newlines test This test is supposed to be testing [b] tag with newlines. --- test/ruby_bbcode_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ruby_bbcode_test.rb b/test/ruby_bbcode_test.rb index 72e8d67..797129e 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 From 61c3d26ebade8e9cf23a7cd409517f7d331e2c48 Mon Sep 17 00:00:00 2001 From: Harry Wood Date: Tue, 8 Nov 2022 10:05:00 +0000 Subject: [PATCH 04/14] Add support for [s] strike-through text Add support for [s] to give strike-through formatting with a "~~" markdown. This is standard bbcode https://www.bbcode.org/making-strikethrough-text-with-bbcode.php --- lib/tags/tags.rb | 4 ++++ test/ruby_bbcode_test.rb | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/tags/tags.rb b/lib/tags/tags.rb index 2471315..484ea6e 100644 --- a/lib/tags/tags.rb +++ b/lib/tags/tags.rb @@ -16,6 +16,10 @@ 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.'}, :center => { :html_open => '', :html_close => '', :description => 'Center a text', diff --git a/test/ruby_bbcode_test.rb b/test/ruby_bbcode_test.rb index 797129e..ffe9e74 100644 --- a/test/ruby_bbcode_test.rb +++ b/test/ruby_bbcode_test.rb @@ -22,6 +22,10 @@ def test_u 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 @@ -157,8 +161,8 @@ 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 From 1552d9115bbce7ce57072cd0e7856293a04318df Mon Sep 17 00:00:00 2001 From: Harry Wood Date: Fri, 4 Nov 2022 14:26:26 +0000 Subject: [PATCH 05/14] Test overriding tags to fix img alt text processing Start a set of tests for processing FluxBB bbcode by passing in an 'additional_tags' list. In this way we can make it do fluxBB-specific things. The first of which is to change treatment of the [img=x] parameter, overriding the defaul WidthxHeight behaviour and allowing passing alt text instead. --- test/fluxbb_test.rb | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 test/fluxbb_test.rb diff --git a/test/fluxbb_test.rb b/test/fluxbb_test.rb new file mode 100644 index 0000000..2be1cce --- /dev/null +++ b/test/fluxbb_test.rb @@ -0,0 +1,31 @@ +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' + ), + } + end + + def test_image_with_alt_text + assert_equal 'FluxBB allows alt text', + '[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 '100x200', + '[img=100x200]http://www.ruby-lang.org/images/header-ruby-logo.png[/img]'.bbcode_to_md(false, fluxbb_tags) + end +end From d0d5bb343c00c1e0c8f3c5e303e3e25e1561793f Mon Sep 17 00:00:00 2001 From: Harry Wood Date: Tue, 8 Nov 2022 03:59:25 +0000 Subject: [PATCH 06/14] Fix handling of paragraphs in children_html When converting bbcode tags to markdown, we run into trouble if there's new paragraphs (double newlines) in their content (in their `children_html`), this may not apply to all bbcode tags, but many of them e.g the basic [b] tag. We cannot output markdown looking like this: ``` **paragraph 1 paragraph 2** ``` It doesn't work (at least not in most markdown processors) An ideal solution might be to output ``` **paragraph 1** **parapgraph 2** ``` To do this properly will entail splitting the processing in two and re-applying our conversion logic to each part (and re-applying any other wrapping bbcode tags). There are data structures which might allow such tricks, but this is too complicated for me to take on right now. The ugly workaround here is to swap in a `
` tag to give the same vertical spacing as a new paragraph while actually being part of the same paragraph. ``` **paragraph 1
paragraph 2** ``` Ugly to look at, and ugly because we're outputting html when we're supposed to be converting to markdown. Furthermore this will only work where
tag is allowed (github and discourse at least). Better solutions welcome! --- lib/ruby-bbcode-to-md/tag_collection.rb | 6 ++++++ lib/tags/tags.rb | 12 ++++++++---- test/ruby_bbcode_test.rb | 5 +++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/ruby-bbcode-to-md/tag_collection.rb b/lib/ruby-bbcode-to-md/tag_collection.rb index 490a91e..1441236 100644 --- a/lib/ruby-bbcode-to-md/tag_collection.rb +++ b/lib/ruby-bbcode-to-md/tag_collection.rb @@ -9,6 +9,12 @@ 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[: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) diff --git a/lib/tags/tags.rb b/lib/tags/tags.rb index 484ea6e..e5b7f09 100644 --- a/lib/tags/tags.rb +++ b/lib/tags/tags.rb @@ -28,12 +28,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 => ' - ', @@ -71,14 +73,16 @@ module Tags :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/ruby_bbcode_test.rb b/test/ruby_bbcode_test.rb index ffe9e74..d935cb2 100644 --- a/test/ruby_bbcode_test.rb +++ b/test/ruby_bbcode_test.rb @@ -17,6 +17,11 @@ 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 From ee5280d50227c3de8ab87799747673c4b998d7ae Mon Sep 17 00:00:00 2001 From: Harry Wood Date: Tue, 8 Nov 2022 04:28:31 +0000 Subject: [PATCH 07/14] Allow :newlines => :to_br tag config Allow a bbcode tag config to force all newlines into
html tags within its children_html. This is useful for outputting markdown headings as follows. Headings need to be all on one line even if the source bbcode allows newline chars. `## My heading
continued on the next line.` Outputting headings? This not part of the bbcode.org standard, but something we would like to be able to do as a custom "additional tag". --- lib/ruby-bbcode-to-md/tag_collection.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/ruby-bbcode-to-md/tag_collection.rb b/lib/ruby-bbcode-to-md/tag_collection.rb index 1441236..4fa7a44 100644 --- a/lib/ruby-bbcode-to-md/tag_collection.rb +++ b/lib/ruby-bbcode-to-md/tag_collection.rb @@ -10,7 +10,9 @@ def to_html(tags) children_html = node.has_children? ? node.children.to_html(tags) : nil if children_html - if node.definition[:paragraphs].nil? || node.definition[:paragraphs] == :to_br + 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 From 77e862b8442505e9476af0e15cb59856c13e81ed Mon Sep 17 00:00:00 2001 From: Harry Wood Date: Fri, 4 Nov 2022 14:43:46 +0000 Subject: [PATCH 08/14] Add [h] tag config Add an example tag config which makes use of the new 'to_br' feature. This is how we would use it for FluxBB (but iobviously doesn't effect default behaviour) --- test/fluxbb_test.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/fluxbb_test.rb b/test/fluxbb_test.rb index 2be1cce..59db167 100644 --- a/test/fluxbb_test.rb +++ b/test/fluxbb_test.rb @@ -11,9 +11,22 @@ def fluxbb_tags :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 'FluxBB allows alt text', '[img=FluxBB allows alt text]http://www.ruby-lang.org/images/header-ruby-logo.png[/img]'.bbcode_to_md(false, fluxbb_tags) From 0be2cb232fd73c73214632416db88c7c8887b16e Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Thu, 12 Jan 2023 16:02:27 +0000 Subject: [PATCH 09/14] New plain_tag config for leaving text analtered Alow a new tag config option, `'plain_tag' => true`, to indicate that all the between text, regardless of what bbcode or other markup characters are in it, should be passed through analtered. --- lib/ruby-bbcode-to-md/tag_sifter.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 From 6d7c8c87a2088dd810e2710f33a73d3935168289 Mon Sep 17 00:00:00 2001 From: Harry Wood Date: Sun, 19 Feb 2023 02:34:30 +0000 Subject: [PATCH 10/14] Add support for [code] Add support for the [code] bbcode, making use of the new plain_text config option. The code block is converted to be wrapped in "```" (on its own line), and crucially the block contents are unaltered by any further parsing. TODO: In fact it will still convert ">" to ">" and other html entities, which ideally it wouldn't, but when calling with `bbcode_to_md(false)` this is disactivated. TODO: We can pass a language to achieve syntax highlighting, such as [code=javascript] in some bbcode flavours, and in the bbcode.org reference. This could be converted to "```javascript" in some markdown flavours. Currently it will just ignore the language information and convert a plain "```" block. --- lib/tags/tags.rb | 5 +++++ test/ruby_bbcode_test.rb | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/lib/tags/tags.rb b/lib/tags/tags.rb index e5b7f09..a708225 100644 --- a/lib/tags/tags.rb +++ b/lib/tags/tags.rb @@ -20,6 +20,11 @@ module Tags :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', diff --git a/test/ruby_bbcode_test.rb b/test/ruby_bbcode_test.rb index d935cb2..48919f1 100644 --- a/test/ruby_bbcode_test.rb +++ b/test/ruby_bbcode_test.rb @@ -43,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 From 598c177893a2508617cee77e1fa9756964293c5e Mon Sep 17 00:00:00 2001 From: Harry Wood Date: Sun, 19 Feb 2023 15:45:18 +0000 Subject: [PATCH 11/14] Add triple nesting test showing wrong output Two test changes to begin tackling two different problems with nested quotes. Firstly add a comment against the first test. This output does not work within discourse. Why talk about discourse specifically? The tag definition for [quote] doesn't do a proper "to markdown" conversion. It remains as bbcode, but with some newlines added. This is presumably to cater for the primary discourse use case, maybe once upon a time it did, but testing in discourse at the moment you cannot place the following test: [quote=Kitten] [quote=creatiu]f1[/quote] f2[/quote] We need a newline after 'f2' otherwise the oute quote is not rendered. Secondly add a test for triple nesting of quotes. This test documents the current output we get, which is clearly not correct. There's no way the letters "EF" should end up next-to eachother. There's a problem with stacked handling of nesting. --- test/ruby_bbcode_test.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/ruby_bbcode_test.rb b/test/ruby_bbcode_test.rb index 48919f1..a930d6f 100644 --- a/test/ruby_bbcode_test.rb +++ b/test/ruby_bbcode_test.rb @@ -74,11 +74,14 @@ def test_whitespace_in_only_allowed_tags 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 "with prefix\n[quote]abc[/quote]\n\n", 'with prefix[quote]abc[/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[quote=creatiu]f1[/quote]\n\nf2[/quote]\n\n", # Not correct for discourse. Needs more newlines '[quote=Kitten][quote=creatiu]f1[/quote]f2[/quote]'.bbcode_to_md + assert_equal "A\n[quote]B\n[quote]C\n[quote]D[/quote]\n\n[/quote]\n\nEF[/quote]\n\nG", # Triple nesting conversion is wrong + 'A[quote]B[quote]C[quote]D[/quote]E[/quote]F[/quote]G'.bbcode_to_md end def test_link From ac6447728531a1ab11c30bcc420d58baba89461e Mon Sep 17 00:00:00 2001 From: Harry Wood Date: Sun, 19 Feb 2023 16:23:43 +0000 Subject: [PATCH 12/14] Fix quotes output to have newlines which work in discourse Fix the conversion of [quotes] to insert more newlines so that the output works in discourse (as it was presumably originally intended to). Note: This changes all the output even for simple quote example, which may be surprising. The original output on one line works OK, but spacing them out onto multiple lines also looks OK. The problem we're fixing here only shows up in more complex nested cases. Specifically this works when we paste it into descourse: [quote=Kitten] [quote=creatiu] f1 [/quote] f2 [/quote] ...but this does not render fully: [quote=Kitten] [quote=creatiu]f1[/quote] f2[/quote] --- lib/tags/tags.rb | 3 +-- test/ruby_bbcode_test.rb | 11 +++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/tags/tags.rb b/lib/tags/tags.rb index a708225..a32620a 100644 --- a/lib/tags/tags.rb +++ b/lib/tags/tags.rb @@ -72,8 +72,7 @@ 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, diff --git a/test/ruby_bbcode_test.rb b/test/ruby_bbcode_test.rb index a930d6f..57f5fe3 100644 --- a/test/ruby_bbcode_test.rb +++ b/test/ruby_bbcode_test.rb @@ -72,15 +72,14 @@ 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 "with prefix\n[quote]abc[/quote]\n\n", 'with prefix[quote]abc[/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", # Not correct for discourse. Needs more newlines + 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]B\n[quote]C\n[quote]D[/quote]\n\n[/quote]\n\nEF[/quote]\n\nG", # Triple nesting conversion is wrong + assert_equal "A\n[quote]\nB\n[quote]\nC\n[quote]\nD\n[/quote]\n\n[/quote]\nEF\n[/quote]\nG", # Triple nesting conversion is wrong 'A[quote]B[quote]C[quote]D[/quote]E[/quote]F[/quote]G'.bbcode_to_md end @@ -158,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 From aaf25ebed46dd53904f657c16409aa59d792ab15 Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Wed, 15 Feb 2023 19:07:31 +0000 Subject: [PATCH 13/14] Track node stack explicitly --- lib/ruby-bbcode-to-md/bbtree.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/ruby-bbcode-to-md/bbtree.rb b/lib/ruby-bbcode-to-md/bbtree.rb index 2bdc963..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... From f5c36c80a24b2721d47f9bec98338699b1620c2c Mon Sep 17 00:00:00 2001 From: Harry Wood Date: Sun, 19 Feb 2023 16:35:13 +0000 Subject: [PATCH 14/14] Triple nesting now works correctly Modify test output to show the correct expected output for the triple-nesting example. Nesting handling is now fixed. --- test/ruby_bbcode_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ruby_bbcode_test.rb b/test/ruby_bbcode_test.rb index 57f5fe3..d8dc916 100644 --- a/test/ruby_bbcode_test.rb +++ b/test/ruby_bbcode_test.rb @@ -79,7 +79,7 @@ def test_quote def test_nested_quotes 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]\n\n[/quote]\nEF\n[/quote]\nG", # Triple nesting conversion is wrong + 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