Search code examples
ruby-on-railsrubyregexquotesbbcode

Removing nested [quote] tags in ruby


I'm writing a forum application in Rails and I'm stuck on limiting nested quotes.

I'm try to use regex and recursion, going down to each matching tag, counting the levels and if the current level is > max, deleting everything inside of it. Problem is that my regex is only matching the first [ quote ] with the first seen [ /quote ], and not the last as intended.

The regex is just a slight tweak of what was given in the docs of the custom bbcode library I'm using (I know very little about regex, I've tried to learn as much as I can in the past couple days but I'm still stuck). I changed it so it'd include [quote], [quote=name] and [quote=name;222] . Could someone examine my code and let me know what the problem could be? I'd appreciate it lots.

def remove_nested_quotes(post_string, max_quotes, count)
    result = post_string.match(/\[quote(:.*)?(?:)?(.*?)(?:)?\](.*?)\[\/quote\1?\]/mi)

    if result.nil?
      return false
    elsif  (count = count+1) > max_quotes
      full_str = result[0]
      offset_beg = result.begin(3)
      offset_end = result.end(3)
      excess_quotes = full_str[offset_beg ..offset_end ]
      new_string = full_str.slice(excess_quotes )
      return new_string
    else
      offset_beg = result.begin(3)
      offset_end = result.end(3)
      full_str = result[0]
      inner_string = full_str[offset_beg..offset_end]
      return remove_nested_quotes(inner_string , max, count)
   end
end

Solution

  • I mean something like

    counter = 0
    max = 5
    
    loop do
        matched = false
        string.match /endquote|quote/ do |match|
           matched = true
           if endquote matched
             counter -= 1     
           else # quote matched
             counter += 1
           end
           if counter > max
             # Do something, break or return             
           else
             string = match.post_match
           end
        end
        break unless matched
    end