Class: Fortitude::Tags::Tag

Inherits:
Object
  • Object
show all
Defined in:
lib/fortitude/tags/tag.rb

Constant Summary collapse

CONCAT_METHOD =
"original_concat"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, options = { }) ⇒ Tag

Returns a new instance of Tag.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/fortitude/tags/tag.rb', line 32

def initialize(name, options = { })
  options.assert_valid_keys(:valid_attributes, :newline_before, :content_allowed, :can_enclose,
    :allow_data_attributes, :allow_aria_attributes, :spec, :escape_direct_content)

  @name = self.class.normalize_tag_name(name)

  self.valid_attributes = options[:valid_attributes]
  self.can_enclose = options[:can_enclose]
  @newline_before = !! options[:newline_before]
  @content_allowed = true unless options.has_key?(:content_allowed) && (! options[:content_allowed])
  @allow_data_attributes = true unless options.has_key?(:allow_data_attributes) && (! options[:allow_data_attributes])
  @allow_aria_attributes = true unless options.has_key?(:allow_aria_attributes) && (! options[:allow_aria_attributes])
  @escape_direct_content = true unless options.has_key?(:escape_direct_content) && (! options[:escape_direct_content])
  @spec = options[:spec]
end

Instance Attribute Details

#allow_aria_attributesObject

Returns the value of attribute allow_aria_attributes.



24
25
26
# File 'lib/fortitude/tags/tag.rb', line 24

def allow_aria_attributes
  @allow_aria_attributes
end

#allow_data_attributesObject

Returns the value of attribute allow_data_attributes.



24
25
26
# File 'lib/fortitude/tags/tag.rb', line 24

def allow_data_attributes
  @allow_data_attributes
end

#content_allowedObject

Returns the value of attribute content_allowed.



24
25
26
# File 'lib/fortitude/tags/tag.rb', line 24

def content_allowed
  @content_allowed
end

#escape_direct_contentObject

Returns the value of attribute escape_direct_content.



24
25
26
# File 'lib/fortitude/tags/tag.rb', line 24

def escape_direct_content
  @escape_direct_content
end

#nameObject (readonly)

Returns the value of attribute name.



23
24
25
# File 'lib/fortitude/tags/tag.rb', line 23

def name
  @name
end

#newline_beforeObject

Returns the value of attribute newline_before.



24
25
26
# File 'lib/fortitude/tags/tag.rb', line 24

def newline_before
  @newline_before
end

#specObject (readonly)

Returns the value of attribute spec.



23
24
25
# File 'lib/fortitude/tags/tag.rb', line 23

def spec
  @spec
end

Class Method Details

.normalize_tag_name(name) ⇒ Object



27
28
29
# File 'lib/fortitude/tags/tag.rb', line 27

def normalize_tag_name(name)
  name.to_s.strip.downcase.to_sym
end

Instance Method Details

#aliased_method_namesObject



173
174
175
# File 'lib/fortitude/tags/tag.rb', line 173

def aliased_method_names
  [ name ]
end

#all_method_namesObject



177
178
179
# File 'lib/fortitude/tags/tag.rb', line 177

def all_method_names
  [ generated_method_name ] + aliased_method_names
end

#can_encloseObject



56
57
58
# File 'lib/fortitude/tags/tag.rb', line 56

def can_enclose
  @allowable_enclosed_elements.keys if @allowable_enclosed_elements
end

#can_enclose=(tags) ⇒ Object



60
61
62
63
# File 'lib/fortitude/tags/tag.rb', line 60

def can_enclose=(tags)
  @allowable_enclosed_elements = to_symbol_hash(tags)
  @allowable_enclosed_elements[:_fortitude_partial_placeholder] = true if @allowable_enclosed_elements
end

#define_method_on!(mod, options = {}) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/fortitude/tags/tag.rb', line 118

def define_method_on!(mod, options = {})
  options.assert_valid_keys(
    :record_emitting_tag, :enforce_attribute_rules, :enable_formatting,
    :enforce_id_uniqueness, :close_void_tags, :allows_bare_attributes)

  unless mod.respond_to?(:fortitude_tag_support_included?) && mod.fortitude_tag_support_included?
    mod.send(:include, ::Fortitude::Tags::TagSupport)
  end

  if @content_allowed
    alone_tag = "<#{name}></#{name}>"
    partial_open_alone_end = "></#{name}>"
  elsif options[:close_void_tags]
    alone_tag = "<#{name}/>"
    partial_open_alone_end = "/>"
  else
    alone_tag = "<#{name}>"
    partial_open_alone_end = ">"
  end

  ensure_constants(mod, :ALONE => alone_tag, :OPEN => "<#{name}>", :CLOSE => "</#{name}>",
    :PARTIAL_OPEN => "<#{name}", :TAG_OBJECT => self, :PARTIAL_OPEN_ALONE_END => partial_open_alone_end)

  needs_formatting = !! options[:enable_formatting]

  if needs_formatting && @newline_before
    yield_call = "_fortitude_formatted_output_tag_yield(:#{name}) { yield }"
  elsif needs_formatting
    yield_call = "yield; rc.about_to_output_non_whitespace!"
  else
    yield_call = "yield"
  end

  text = Fortitude::MethodTemplates::SimpleCompiledTemplate.template('tag_method_template').result(
    :name => name.to_s, :method_name => generated_method_name.to_s, :yield_call => yield_call, :concat_method => CONCAT_METHOD,
    :record_emitting_tag => (!! options[:record_emitting_tag]),
    :needs_attribute_rules => !! options[:enforce_attribute_rules],
    :needs_id_uniqueness => !! options[:enforce_id_uniqueness],
    :allows_bare_attributes => (!! options[:allows_bare_attributes]),
    :needs_formatting => needs_formatting, :content_allowed => @content_allowed,
    :newline_before => @newline_before,
    :escape_direct_content => @escape_direct_content,
    :alone_const => tag_constant_name(:ALONE), :open_const => tag_constant_name(:OPEN),
    :close_const => tag_constant_name(:CLOSE), :partial_open_const => tag_constant_name(:PARTIAL_OPEN),
    :tag_object_const => tag_constant_name(:TAG_OBJECT), :partial_open_end_const => :FORTITUDE_TAG_PARTIAL_OPEN_END,
    :partial_open_alone_end_const => tag_constant_name(:PARTIAL_OPEN_ALONE_END))

  mod.module_eval(text)
  aliased_method_names.each { |an| mod.alias_method(an, generated_method_name) }
end

#dupObject



65
66
67
68
69
70
71
72
73
74
75
# File 'lib/fortitude/tags/tag.rb', line 65

def dup
  self.class.new(name, {
    :valid_attributes => valid_attributes,
    :can_enclose => can_enclose,
    :content_allowed => content_allowed,
    :allow_data_attributes => allow_data_attributes,
    :allow_aria_attributes => allow_aria_attributes,
    :escape_direct_content => escape_direct_content,
    :spec => spec
  })
end

#generated_method_nameObject



169
170
171
# File 'lib/fortitude/tags/tag.rb', line 169

def generated_method_name
  "tag_#{name}"
end

#is_valid_attribute?(k, v) ⇒ Boolean

Returns:

  • (Boolean)


99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/fortitude/tags/tag.rb', line 99

def is_valid_attribute?(k, v)
  return true if @allowable_attributes.include?(k.to_sym)

  if @allow_data_attributes
    return true if k.to_s =~ /^data-\S/i || (k.to_s =~ /^data$/i && v.kind_of?(Hash))
  end

  if @allow_aria_attributes
    return true if k.to_s =~ /^aria-\S/i || (k.to_s =~ /^aria$/i && v.kind_of?(Hash))
  end

  return false
end

#valid_attributesObject



48
49
50
# File 'lib/fortitude/tags/tag.rb', line 48

def valid_attributes
  @allowable_attributes.keys if @allowable_attributes
end

#valid_attributes=(attributes) ⇒ Object



52
53
54
# File 'lib/fortitude/tags/tag.rb', line 52

def valid_attributes=(attributes)
  @allowable_attributes = to_symbol_hash(attributes)
end

#validate_attributes(widget, attributes_hash) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/fortitude/tags/tag.rb', line 86

def validate_attributes(widget, attributes_hash)
  return unless @allowable_attributes
  disabled_sym = attributes_hash.delete(:_fortitude_skip_attribute_rule_enforcement)
  disabled_string = attributes_hash.delete('_fortitude_skip_attribute_rule_enforcement')
  return if disabled_sym || disabled_string
  return if widget.rendering_context.attribute_validation_disabled?
  bad = { }
  attributes_hash.each do |k, v|
    bad[k] = v unless is_valid_attribute?(k, v)
  end
  raise Fortitude::Errors::InvalidElementAttributes.new(widget, self, bad, @allowable_attributes.keys) if bad.size > 0
end

#validate_can_enclose!(widget, tag_object) ⇒ Object



79
80
81
82
83
84
# File 'lib/fortitude/tags/tag.rb', line 79

def validate_can_enclose!(widget, tag_object)
  return unless @allowable_enclosed_elements
  unless @allowable_enclosed_elements[tag_object.name]
    raise Fortitude::Errors::InvalidElementNesting.new(widget, self, tag_object)
  end
end

#validate_id_uniqueness(widget, attributes_hash) ⇒ Object



113
114
115
116
# File 'lib/fortitude/tags/tag.rb', line 113

def validate_id_uniqueness(widget, attributes_hash)
  id = attributes_hash[:id] || attributes_hash['id']
  widget.rendering_context.validate_id_uniqueness(widget, name, id) if id
end