Class: RubyBBCode::TagSifter

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby-bbcode/tag_sifter.rb

Overview

TagSifter is in charge of building up the BBTree with nodes as it parses through the supplied text such as

"[b]I'm bold and the next word is [i]ITALIC[/i][b]"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(text_to_parse, dictionary, escape_html = true) ⇒ TagSifter

Returns a new instance of TagSifter.



10
11
12
13
14
15
16
17
# File 'lib/ruby-bbcode/tag_sifter.rb', line 10

def initialize(text_to_parse, dictionary, escape_html = true)
  @text = escape_html ? text_to_parse.gsub('<', '&lt;').gsub('>', '&gt;').gsub('"', "&quot;") : text_to_parse
  
  @dictionary = dictionary # the dictionary for all the defined tags in tags.rb
  @bbtree = BBTree.new({:nodes => TagCollection.new}, dictionary)
  @ti = nil
  @errors = false
end

Instance Attribute Details

#bbtreeObject (readonly)

Returns the value of attribute bbtree.



8
9
10
# File 'lib/ruby-bbcode/tag_sifter.rb', line 8

def bbtree
  @bbtree
end

#errorsObject (readonly)

Returns the value of attribute errors.



8
9
10
# File 'lib/ruby-bbcode/tag_sifter.rb', line 8

def errors
  @errors
end

Instance Method Details

#get_proper_tagObject



86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/ruby-bbcode/tag_sifter.rb', line 86

def get_proper_tag
  supported_tags = @bbtree.current_node[:definition][:supported_tags]

  supported_tags.each do |tag|
    regex_list = @dictionary[tag][:url_matches]
    
    regex_list.each do |regex|
      return tag if regex =~ @ti.tag_data[:text]
    end
  end
  :tag_not_found
end

#handle_closing_tags_that_are_multi_as_text_if_it_doesnt_match_the_latest_opener_tag_on_the_stackObject



99
100
101
102
103
104
105
106
107
108
109
# File 'lib/ruby-bbcode/tag_sifter.rb', line 99

def handle_closing_tags_that_are_multi_as_text_if_it_doesnt_match_the_latest_opener_tag_on_the_stack
  if @ti.element_is_closing_tag?
    return if @bbtree.current_node[:definition].nil?
    if parent_tag != @ti[:tag].to_sym and @bbtree.current_node[:definition][:multi_tag]       # if opening tag doesn't match this closing tag... and if the opener was a multi_tag...
      @ti[:is_tag] = false
      @ti[:closing_tag] = false
      @ti[:text] = @ti.tag_data[:complete_match]
    end
  end
  
end

#invalid?Boolean

Returns:

  • (Boolean)


19
20
21
# File 'lib/ruby-bbcode/tag_sifter.rb', line 19

def invalid?
  @errors != false
end

#process_textObject

BBTree#process_text is responsible for parsing the actual BBCode text and converting it into a ‘syntax tree’ of nodes, each node represeting either a tag type or content for a tag once this tree is built, the to_html method can be invoked where the tree is finally converted into HTML syntax.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/ruby-bbcode/tag_sifter.rb', line 27

def process_text
  regex_string = '((\[ (\/)? ( \* | (\w+)) ((=[^\[\]]+) | (\s\w+=\w+)* | ([^\]]*))? \]) | ([^\[]+))'
  @text.scan(/#{regex_string}/ix) do |tag_info|
    @ti = TagInfo.new(tag_info, @dictionary)
    
    @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
    
    return if !valid_element?
    
    case @ti.type   # Validation of tag succeeded, add to @bbtree.tags_list and/or bbtree
    when :opening_tag
      element = {:is_tag => true, :tag => @ti[:tag].to_sym, :definition => @ti.definition, :nodes => TagCollection.new }
      element[:params] = {:tag_param => get_formatted_element_params} if @ti.can_have_params? and @ti.has_params?
      
      @bbtree.retrogress_bbtree if self_closing_tag_reached_a_closer?
      
      @bbtree.build_up_new_tag(element)
      
      @bbtree.escalate_bbtree(element)
    when :text
      set_parent_tag_from_multi_tag_to_concrete! if @bbtree.current_node.definition && @bbtree.current_node.definition[:multi_tag] == true
      element = {:is_tag => false, :text => @ti.text }
      if within_open_tag?
        tag = @bbtree.current_node.definition
        if tag[:require_between]
          @bbtree.current_node[:between] = get_formatted_element_params
          if candidate_for_using_between_as_param?
            use_between_as_tag_param    # Did not specify tag_param, so use between text.
          end
          next  # don't add this node to @bbtree.current_node.children if we're within an open tag that requires_between (to be a param), and the between couldn't be used as a param... Yet it passed validation so the param must have been specified within the opening tag???
        end
      end
      @bbtree.build_up_new_tag(element)
    when :closing_tag
      @bbtree.retrogress_bbtree if parent_of_self_closing_tag? and @bbtree.within_open_tag?
      @bbtree.retrogress_bbtree
    end
    
  end # end of scan loop
  
  validate_all_tags_closed_off   # TODO: consider automatically closing off all the tags... I think that's how the HTML 5 parser works too
  validate_stack_level_too_deep_potential
end

#set_parent_tag_from_multi_tag_to_concrete!Object



72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/ruby-bbcode/tag_sifter.rb', line 72

def set_parent_tag_from_multi_tag_to_concrete!
  # if the proper tag can't be matched, we need to treat the parent tag as text instead!  Or throw an error message....
  
  proper_tag = get_proper_tag
  if proper_tag == :tag_not_found
    @bbtree.redefine_parent_tag_as_text
    
    @bbtree.nodes << TagNode.new(@ti.tag_data)      # escalate the bbtree with this element as though it's regular text data...
    return
  end
  @bbtree.current_node[:definition] = @dictionary[proper_tag]
  @bbtree.current_node[:tag] = proper_tag
end