ruby-bbcode-to-md 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.md +41 -0
- data/Rakefile +44 -0
- data/lib/ruby-bbcode.rb +100 -0
- data/lib/ruby-bbcode/bbtree.rb +94 -0
- data/lib/ruby-bbcode/debugging.rb +93 -0
- data/lib/ruby-bbcode/tag_collection.rb +116 -0
- data/lib/ruby-bbcode/tag_info.rb +132 -0
- data/lib/ruby-bbcode/tag_node.rb +67 -0
- data/lib/ruby-bbcode/tag_sifter.rb +303 -0
- data/lib/ruby-bbcode/version.rb +3 -0
- data/lib/tags/tags.rb +113 -0
- data/test/current_test.rb +8 -0
- data/test/ruby_bbcode_test.rb +208 -0
- data/test/test_helper.rb +18 -0
- data/test/unit/debugging_test.rb +47 -0
- data/test/unit/tag_sifter_test.rb +51 -0
- metadata +117 -0
@@ -0,0 +1,132 @@
|
|
1
|
+
module RubyBBCode
|
2
|
+
# tag info is basically what the regex scan get's converted into
|
3
|
+
# during the tag_sifter#process_text method.
|
4
|
+
# This class was made mostly just to keep track of all of the confusing
|
5
|
+
# the logic conditions that are checked.
|
6
|
+
#
|
7
|
+
class TagInfo
|
8
|
+
def initialize(tag_info, dictionary)
|
9
|
+
@tag_data = find_tag_info(tag_info)
|
10
|
+
@dictionary = dictionary
|
11
|
+
@definition = @dictionary[@tag_data[:tag].to_sym] unless @tag_data[:tag].nil?
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
@tag_data[key]
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(key, value)
|
19
|
+
@tag_data[key] = value
|
20
|
+
end
|
21
|
+
|
22
|
+
def tag_data
|
23
|
+
@tag_data
|
24
|
+
end
|
25
|
+
|
26
|
+
def definition
|
27
|
+
@definition
|
28
|
+
end
|
29
|
+
|
30
|
+
def definition=(val)
|
31
|
+
@definition = val
|
32
|
+
end
|
33
|
+
|
34
|
+
def dictionary # need this for reasigning multi_tag elements
|
35
|
+
@dictionary
|
36
|
+
end
|
37
|
+
|
38
|
+
# This represents the text value of the element (if it's not a tag element)
|
39
|
+
# Newlines are converted to html <br /> syntax before being returned.
|
40
|
+
def text
|
41
|
+
text = @tag_data[:text]
|
42
|
+
# convert_newlines_to_br
|
43
|
+
text.gsub!("\r\n", "\n")
|
44
|
+
text.gsub!("\n", "\n")
|
45
|
+
text
|
46
|
+
end
|
47
|
+
|
48
|
+
# allows for a very snazy case/ when conditional
|
49
|
+
def type
|
50
|
+
return :opening_tag if element_is_opening_tag?
|
51
|
+
return :text if element_is_text?
|
52
|
+
return :closing_tag if element_is_closing_tag?
|
53
|
+
end
|
54
|
+
|
55
|
+
def handle_unregistered_tags_as_text
|
56
|
+
if element_is_tag? and tag_missing_from_tag_dictionary?
|
57
|
+
# Handle as text from now on!
|
58
|
+
self[:is_tag] = false
|
59
|
+
self[:closing_tag] = false
|
60
|
+
self[:text] = self[:complete_match]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def element_is_tag?
|
65
|
+
self[:is_tag]
|
66
|
+
end
|
67
|
+
|
68
|
+
def element_is_opening_tag?
|
69
|
+
self[:is_tag] and !self[:closing_tag]
|
70
|
+
end
|
71
|
+
|
72
|
+
def element_is_closing_tag?
|
73
|
+
self[:closing_tag]
|
74
|
+
end
|
75
|
+
|
76
|
+
def element_is_text?
|
77
|
+
!self[:text].nil?
|
78
|
+
end
|
79
|
+
|
80
|
+
def has_params?
|
81
|
+
self[:params][:tag_param] != nil
|
82
|
+
end
|
83
|
+
|
84
|
+
def tag_missing_from_tag_dictionary?
|
85
|
+
!@dictionary.include?(self[:tag].to_sym)
|
86
|
+
end
|
87
|
+
|
88
|
+
def allowed_outside_parent_tags?
|
89
|
+
@definition[:only_in].nil?
|
90
|
+
end
|
91
|
+
|
92
|
+
def constrained_to_within_parent_tags?
|
93
|
+
!@definition[:only_in].nil?
|
94
|
+
end
|
95
|
+
|
96
|
+
def allowed_in(tag_symbol)
|
97
|
+
@definition[:only_in].include?(tag_symbol)
|
98
|
+
end
|
99
|
+
|
100
|
+
def can_have_params?
|
101
|
+
@definition[:allow_tag_param]
|
102
|
+
end
|
103
|
+
|
104
|
+
# Checks if the tag param matches the regex pattern defined in tags.rb
|
105
|
+
def invalid_param?
|
106
|
+
self[:params][:tag_param].match(@definition[:tag_param]).nil?
|
107
|
+
end
|
108
|
+
|
109
|
+
protected
|
110
|
+
|
111
|
+
def find_tag_info(tag_info)
|
112
|
+
ti = {}
|
113
|
+
ti[:complete_match] = tag_info[0]
|
114
|
+
ti[:is_tag] = (tag_info[0].start_with? '[')
|
115
|
+
if ti[:is_tag]
|
116
|
+
ti[:closing_tag] = (tag_info[2] == '/')
|
117
|
+
ti[:tag] = tag_info[3]
|
118
|
+
ti[:params] = {}
|
119
|
+
if tag_info[4][0] == ?=
|
120
|
+
ti[:params][:tag_param] = tag_info[4][1..-1]
|
121
|
+
elsif tag_info[4][0] == ?\s
|
122
|
+
#FIXME: Find params... Delete this or write a test to cover this and implement it
|
123
|
+
end
|
124
|
+
else
|
125
|
+
# Plain text
|
126
|
+
ti[:text] = tag_info[8]
|
127
|
+
end
|
128
|
+
ti
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module RubyBBCode
|
2
|
+
# TagNodes are nodes that are stored up in the BBTree's @current_node.children array I think... which is a bit misleading...
|
3
|
+
#
|
4
|
+
# TagNodes specify either opening tag elements or text elements... TagInfo elements are essentially converted into these nodes which are
|
5
|
+
# later converted into html output in the bbtree_to_html method
|
6
|
+
class TagNode
|
7
|
+
include ::RubyBBCode::DebugBBTree
|
8
|
+
attr_accessor :element
|
9
|
+
|
10
|
+
def initialize(element, nodes = [])
|
11
|
+
@element = element # { :is_tag=>false, :text=>"ITALLICS" } || { :is_tag=>true, :tag=>:i, :nodes => [] }
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
@element[key]
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(key, value)
|
19
|
+
@element[key] = value
|
20
|
+
end
|
21
|
+
|
22
|
+
# Debugging/ visualization purposes
|
23
|
+
def type
|
24
|
+
return :tag if @element[:is_tag]
|
25
|
+
return :text if !@element[:is_tag]
|
26
|
+
end
|
27
|
+
|
28
|
+
def parent_type
|
29
|
+
@element[:parent_tag]
|
30
|
+
end
|
31
|
+
|
32
|
+
# Checks to see if the parameter for the TagNode has been set.
|
33
|
+
def param_not_set?
|
34
|
+
(@element[:params].nil? or @element[:params][:tag_param].nil?)
|
35
|
+
end
|
36
|
+
|
37
|
+
# check if the parameter for the TagNode is set
|
38
|
+
def param_set?
|
39
|
+
!param_not_set?
|
40
|
+
end
|
41
|
+
|
42
|
+
def has_children?
|
43
|
+
return false if type == :text or children.length == 0 # text nodes return false too
|
44
|
+
return true if children.length > 0
|
45
|
+
end
|
46
|
+
|
47
|
+
def allow_tag_param?
|
48
|
+
definition[:allow_tag_param]
|
49
|
+
end
|
50
|
+
|
51
|
+
# shows the tag definition for this TagNode as defined in tags.rb
|
52
|
+
def definition
|
53
|
+
@element[:definition]
|
54
|
+
end
|
55
|
+
|
56
|
+
def children
|
57
|
+
@element[:nodes]
|
58
|
+
end
|
59
|
+
|
60
|
+
# Easy way to set the tag_param value of the hash, which represents
|
61
|
+
# the parameter supplied
|
62
|
+
def tag_param=(param)
|
63
|
+
@element[:params] = {:tag_param => param}
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,303 @@
|
|
1
|
+
module RubyBBCode
|
2
|
+
# Tag sifter is in charge of building up the BBTree with nodes as it parses through the
|
3
|
+
# supplied text such as "[b]hello world[/b]"
|
4
|
+
class TagSifter
|
5
|
+
attr_reader :bbtree, :errors
|
6
|
+
|
7
|
+
def initialize(text_to_parse, dictionary, escape_html = true)
|
8
|
+
@text = escape_html ? text_to_parse.gsub('<', '<').gsub('>', '>').gsub('"', """) : text_to_parse
|
9
|
+
|
10
|
+
@dictionary = dictionary # the dictionary for all the defined tags in tags.rb
|
11
|
+
@bbtree = BBTree.new({:nodes => TagCollection.new}, dictionary)
|
12
|
+
@ti = nil
|
13
|
+
@errors = false
|
14
|
+
end
|
15
|
+
|
16
|
+
def invalid?
|
17
|
+
@errors != false
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def process_text
|
22
|
+
regex_string = '((\[ (\/)? (\w+) ((=[^\[\]]+) | (\s\w+=\w+)* | ([^\]]*))? \]) | ([^\[]+))'
|
23
|
+
@text.scan(/#{regex_string}/ix) do |tag_info|
|
24
|
+
@ti = TagInfo.new(tag_info, @dictionary)
|
25
|
+
|
26
|
+
@ti.handle_unregistered_tags_as_text # if the tag isn't in the @dictionary list, then treat it as text
|
27
|
+
handle_closing_tags_that_are_multi_as_text_if_it_doesnt_match_the_latest_opener_tag_on_the_stack
|
28
|
+
|
29
|
+
return if !valid_element?
|
30
|
+
|
31
|
+
case @ti.type # Validation of tag succeeded, add to @bbtree.tags_list and/or bbtree
|
32
|
+
when :opening_tag
|
33
|
+
element = {:is_tag => true, :tag => @ti[:tag].to_sym, :definition => @ti.definition, :nodes => TagCollection.new }
|
34
|
+
element[:params] = {:tag_param => get_formatted_element_params} if @ti.can_have_params? and @ti.has_params?
|
35
|
+
@bbtree.build_up_new_tag(element)
|
36
|
+
|
37
|
+
@bbtree.escalate_bbtree(element)
|
38
|
+
when :text
|
39
|
+
set_parent_tag_from_multi_tag_to_concrete! if @bbtree.current_node.definition && @bbtree.current_node.definition[:multi_tag] == true
|
40
|
+
element = {:is_tag => false, :text => @ti.text }
|
41
|
+
if within_open_tag?
|
42
|
+
tag = @bbtree.current_node.definition
|
43
|
+
if tag[:require_between]
|
44
|
+
@bbtree.current_node[:between] = get_formatted_element_params
|
45
|
+
if candidate_for_using_between_as_param?
|
46
|
+
use_between_as_tag_param # Did not specify tag_param, so use between text.
|
47
|
+
end
|
48
|
+
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???
|
49
|
+
end
|
50
|
+
end
|
51
|
+
@bbtree.build_up_new_tag(element)
|
52
|
+
when :closing_tag
|
53
|
+
@bbtree.retrogress_bbtree
|
54
|
+
end
|
55
|
+
|
56
|
+
end # end of scan loop
|
57
|
+
|
58
|
+
validate_all_tags_closed_off # TODO: consider automatically closing off all the tags... I think that's how the HTML 5 parser works too
|
59
|
+
validate_stack_level_too_deep_potential
|
60
|
+
end
|
61
|
+
|
62
|
+
def set_parent_tag_from_multi_tag_to_concrete!
|
63
|
+
# if the proper tag can't be matched, we need to treat the parent tag as text instead! Or throw an error message....
|
64
|
+
|
65
|
+
proper_tag = get_proper_tag
|
66
|
+
if proper_tag == :tag_not_found
|
67
|
+
#binding.pry
|
68
|
+
@bbtree.redefine_parent_tag_as_text
|
69
|
+
|
70
|
+
@bbtree.nodes << TagNode.new(@ti.tag_data) # escilate the bbtree with this element as though it's regular text data...
|
71
|
+
return
|
72
|
+
end
|
73
|
+
@bbtree.current_node[:definition] = @dictionary[proper_tag]
|
74
|
+
@bbtree.current_node[:tag] = proper_tag
|
75
|
+
end
|
76
|
+
|
77
|
+
def get_proper_tag
|
78
|
+
supported_tags = @bbtree.current_node[:definition][:supported_tags]
|
79
|
+
|
80
|
+
supported_tags.each do |tag|
|
81
|
+
regex_list = @dictionary[tag][:url_matches]
|
82
|
+
|
83
|
+
regex_list.each do |regex|
|
84
|
+
return tag if regex =~ @ti.tag_data[:text]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
:tag_not_found
|
88
|
+
end
|
89
|
+
|
90
|
+
def handle_closing_tags_that_are_multi_as_text_if_it_doesnt_match_the_latest_opener_tag_on_the_stack
|
91
|
+
if @ti.element_is_closing_tag?
|
92
|
+
return if @bbtree.current_node[:definition].nil?
|
93
|
+
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...
|
94
|
+
@ti[:is_tag] = false
|
95
|
+
@ti[:closing_tag] = false
|
96
|
+
@ti[:text] = @ti.tag_data[:complete_match]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
# This method allows us to format params if needed...
|
106
|
+
# TODO: Maybe this kind of thing *could* be handled in the bbtree_to_html where the %between% is
|
107
|
+
# sorted out and the html is generated, but... That code has yet to be refactored and we can.
|
108
|
+
# refactor this code easily to happen over there if necessary... Yes, I think it's more logical
|
109
|
+
# to be put over there, but that method needs to be cleaned up before we introduce the formatting overthere... and knowing the parent node is helpful!
|
110
|
+
def get_formatted_element_params
|
111
|
+
if @ti[:is_tag]
|
112
|
+
param = @ti[:params][:tag_param]
|
113
|
+
if @ti.can_have_params? and @ti.has_params?
|
114
|
+
# perform special formatting for cenrtain tags
|
115
|
+
param = conduct_special_formatting(param) if @ti[:tag].to_sym == :youtube # note: this line isn't ever used because @@tags don't allow it... I think if we have tags without the same kind of :require_between restriction, we'll need to pay close attention to this case
|
116
|
+
end
|
117
|
+
return param
|
118
|
+
else # must be text... @ti[:is_tag] == false
|
119
|
+
param = @ti[:text]
|
120
|
+
# perform special formatting for cenrtain tags
|
121
|
+
param = conduct_special_formatting(param) if @bbtree.current_node.definition[:url_matches]
|
122
|
+
return param
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def conduct_special_formatting(url, regex_matches = nil)
|
127
|
+
regex_matches = @bbtree.current_node.definition[:url_matches] if regex_matches.nil? # for testing purposes we can force in regex_matches
|
128
|
+
|
129
|
+
regex_matches.each do |regex|
|
130
|
+
if url =~ regex
|
131
|
+
id = $1
|
132
|
+
return id
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
return url # if we couldn't find a match, then just return the url, hopefully it's a valid youtube ID...
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
# Validates the element
|
141
|
+
def valid_element?
|
142
|
+
return false if !valid_text_or_opening_element?
|
143
|
+
return false if !valid_closing_element?
|
144
|
+
return false if !valid_param_supplied_as_text?
|
145
|
+
true
|
146
|
+
end
|
147
|
+
|
148
|
+
def valid_text_or_opening_element?
|
149
|
+
if @ti.element_is_text? or @ti.element_is_opening_tag?
|
150
|
+
return false if validate_opening_tag == false
|
151
|
+
return false if validate_constraints_on_child == false
|
152
|
+
end
|
153
|
+
true
|
154
|
+
end
|
155
|
+
|
156
|
+
def validate_opening_tag
|
157
|
+
# TODO: rename this if statement to #validate_opening_tag
|
158
|
+
if @ti.element_is_opening_tag?
|
159
|
+
unless @ti.allowed_outside_parent_tags? or (within_open_tag? and @ti.allowed_in(parent_tag.to_sym))
|
160
|
+
# Tag doesn't belong in the last opened tag
|
161
|
+
throw_child_requires_specific_parent_error; return false
|
162
|
+
end
|
163
|
+
|
164
|
+
# Originally: tag[:allow_tag_param] and ti[:params][:tag_param] != nil
|
165
|
+
if @ti.can_have_params? and @ti.has_params?
|
166
|
+
# Test if matches
|
167
|
+
if @ti.invalid_param?
|
168
|
+
throw_invalid_param_error; return false
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
true
|
173
|
+
end
|
174
|
+
|
175
|
+
def validate_constraints_on_child
|
176
|
+
# TODO: Rename this if statement to #validate_constraints_on_child
|
177
|
+
if within_open_tag? and parent_has_constraints_on_children?
|
178
|
+
# Check if the found tag is allowed
|
179
|
+
last_tag = @dictionary[parent_tag]
|
180
|
+
allowed_tags = last_tag[:only_allow]
|
181
|
+
if (!@ti[:is_tag] and last_tag[:require_between] != true and @ti[:text].lstrip != "") or (@ti[:is_tag] and (allowed_tags.include?(@ti[:tag].to_sym) == false)) # TODO: refactor this, it's just too long
|
182
|
+
# Last opened tag does not allow tag
|
183
|
+
throw_parent_prohibits_this_child_error; return false
|
184
|
+
end
|
185
|
+
end
|
186
|
+
true
|
187
|
+
end
|
188
|
+
|
189
|
+
def valid_closing_element?
|
190
|
+
tag = @ti.definition
|
191
|
+
|
192
|
+
if @ti.element_is_closing_tag?
|
193
|
+
if parent_tag != @ti[:tag].to_sym
|
194
|
+
@errors = ["Closing tag [/#{@ti[:tag]}] does match [#{parent_tag}]"]
|
195
|
+
return false
|
196
|
+
end
|
197
|
+
|
198
|
+
if tag[:require_between] == true and @bbtree.current_node[:between].nil?
|
199
|
+
@errors = ["No text between [#{@ti[:tag]}] and [/#{@ti[:tag]}] tags."]
|
200
|
+
return false
|
201
|
+
end
|
202
|
+
end
|
203
|
+
true
|
204
|
+
end
|
205
|
+
|
206
|
+
# This validation is for text elements with between text
|
207
|
+
# that might be construed as a param.
|
208
|
+
# The validation code checks if the params match constraints
|
209
|
+
# imposed by the node/tag/parent.
|
210
|
+
def valid_param_supplied_as_text?
|
211
|
+
tag = @bbtree.current_node.definition
|
212
|
+
|
213
|
+
# this conditional ensures whether the validation is apropriate to this tag type
|
214
|
+
if @ti.element_is_text? and within_open_tag? and tag[:require_between] and candidate_for_using_between_as_param?
|
215
|
+
|
216
|
+
# check if valid
|
217
|
+
if @ti[:text].match(tag[:tag_param]).nil?
|
218
|
+
@errors = [tag[:tag_param_description].gsub('%param%', @ti[:text])]
|
219
|
+
return false
|
220
|
+
end
|
221
|
+
end
|
222
|
+
true
|
223
|
+
end
|
224
|
+
|
225
|
+
def validate_all_tags_closed_off
|
226
|
+
# if we're still expecting a closing tag and we've come to the end of the string... throw error
|
227
|
+
throw_unexpected_end_of_string_error if expecting_a_closing_tag?
|
228
|
+
end
|
229
|
+
|
230
|
+
def validate_stack_level_too_deep_potential
|
231
|
+
if @bbtree.nodes.count > 2200
|
232
|
+
throw_stack_level_will_be_too_deep_error
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def throw_child_requires_specific_parent_error
|
237
|
+
err = "[#{@ti[:tag]}] can only be used in [#{@ti.definition[:only_in].to_sentence(to_sentence_bbcode_tags)}]"
|
238
|
+
err += ", so using it in a [#{parent_tag}] tag is not allowed" if expecting_a_closing_tag?
|
239
|
+
@errors = [err]
|
240
|
+
end
|
241
|
+
|
242
|
+
def throw_invalid_param_error
|
243
|
+
@errors = [@ti.definition[:tag_param_description].gsub('%param%', @ti[:params][:tag_param])]
|
244
|
+
end
|
245
|
+
|
246
|
+
def throw_parent_prohibits_this_child_error
|
247
|
+
allowed_tags = @dictionary[parent_tag][:only_allow]
|
248
|
+
err = "[#{parent_tag}] can only contain [#{allowed_tags.to_sentence(to_sentence_bbcode_tags)}] tags, so "
|
249
|
+
err += "[#{@ti[:tag]}]" if @ti[:is_tag]
|
250
|
+
err += "\"#{@ti[:text]}\"" unless @ti[:is_tag]
|
251
|
+
err += ' is not allowed'
|
252
|
+
@errors = [err]
|
253
|
+
end
|
254
|
+
|
255
|
+
def throw_unexpected_end_of_string_error
|
256
|
+
@errors = ["[#{@bbtree.tags_list.to_sentence(to_sentence_bbcode_tags)}] not closed"]
|
257
|
+
end
|
258
|
+
|
259
|
+
def throw_stack_level_will_be_too_deep_error
|
260
|
+
@errors = ["Stack level would go too deep. You must be trying to process a text containing thousands of BBTree nodes at once. (limit around 2300 tags containing 2,300 strings). Check RubyBBCode::TagCollection#to_html to see why this validation is needed."]
|
261
|
+
end
|
262
|
+
|
263
|
+
|
264
|
+
def to_sentence_bbcode_tags
|
265
|
+
{:words_connector => "], [",
|
266
|
+
:two_words_connector => "] and [",
|
267
|
+
:last_word_connector => "] and ["}
|
268
|
+
end
|
269
|
+
|
270
|
+
|
271
|
+
def expecting_a_closing_tag?
|
272
|
+
@bbtree.expecting_a_closing_tag?
|
273
|
+
end
|
274
|
+
|
275
|
+
def within_open_tag?
|
276
|
+
@bbtree.within_open_tag?
|
277
|
+
end
|
278
|
+
|
279
|
+
def use_between_as_tag_param
|
280
|
+
param = get_formatted_element_params
|
281
|
+
@bbtree.current_node.tag_param = param # @bbtree.current_node[:params] = {:tag_param => @ti[:text]}
|
282
|
+
end
|
283
|
+
|
284
|
+
def candidate_for_using_between_as_param?
|
285
|
+
# TODO: the bool values...
|
286
|
+
# are unclear and should be worked on. Additional tag might be tag[:requires_param] such that
|
287
|
+
# [img] would have that as true... and [url] would have that as well...
|
288
|
+
# as it is now, if a tag (say youtube) has tag[:require_between] == true and tag[:allow_tag_param].nil?
|
289
|
+
# then the :between is assumed to be the param... that is, a tag that should respond 'true' to tag.requires_param?
|
290
|
+
tag = @bbtree.current_node.definition
|
291
|
+
tag[:allow_tag_param_between] and @bbtree.current_node.param_not_set?
|
292
|
+
end
|
293
|
+
|
294
|
+
def parent_tag
|
295
|
+
@bbtree.parent_tag
|
296
|
+
end
|
297
|
+
|
298
|
+
def parent_has_constraints_on_children?
|
299
|
+
@bbtree.parent_has_constraints_on_children?
|
300
|
+
end
|
301
|
+
|
302
|
+
end
|
303
|
+
end
|