Class: Hanami::View::Helpers::TagHelper::TagBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/hanami/view/helpers/tag_helper/tag_builder.rb

Overview

Tag builder returned from #tag.

See Also:

Since:

  • 2.1.0

Constant Summary collapse

HTML_VOID_ELEMENTS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0

%i(
  area base br col embed hr img input keygen link meta param source track wbr
).to_set
SVG_SELF_CLOSING_ELEMENTS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0

%i(
  animate animateMotion animateTransform circle ellipse line path polygon polyline rect set stop use view
).to_set
ATTRIBUTE_SEPARATOR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0

" "
BOOLEAN_ATTRIBUTES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0

%w(
  allowfullscreen allowpaymentrequest async autofocus
  autoplay checked compact controls declare default
  defaultchecked defaultmuted defaultselected defer
  disabled enabled formnovalidate hidden indeterminate
  inert ismap itemscope loop multiple muted nohref
  nomodule noresize noshade novalidate nowrap open
  pauseonexit playsinline readonly required reversed
  scoped seamless selected sortable truespeed
  typemustmatch visible
).to_set
ARIA_PREFIXES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0

["aria", :aria].to_set.freeze
DATA_PREFIXES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0

["data", :data].to_set.freeze
TAG_TYPES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0

{}.tap do |hsh|
  BOOLEAN_ATTRIBUTES.each { |attr| hsh[attr] = :boolean }
  DATA_PREFIXES.each { |attr| hsh[attr] = :data }
  ARIA_PREFIXES.each { |attr| hsh[attr] = :aria }
  hsh.freeze
end
PRE_CONTENT_STRINGS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0

Hash.new { "" }

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(inflector:) ⇒ TagBuilder

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of TagBuilder.

Since:

  • 2.1.0



79
80
81
# File 'lib/hanami/view/helpers/tag_helper/tag_builder.rb', line 79

def initialize(inflector:)
  @inflector = inflector
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(called, *args, **options, &block) ⇒ Object (private)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0



205
206
207
# File 'lib/hanami/view/helpers/tag_helper/tag_builder.rb', line 205

def method_missing(called, *args, **options, &block)
  tag_string(called, *args, **options, &block)
end

Instance Attribute Details

#inflectorObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0



75
76
77
# File 'lib/hanami/view/helpers/tag_helper/tag_builder.rb', line 75

def inflector
  @inflector
end

Instance Method Details

#attributes(**attributes) ⇒ Object

Transforms a Hash into HTML Attributes, ready to be interpolated into ERB.

Examples:

<input <%= tag.attributes(type: :text, aria: { label: "Search" }) %> >
# => <input type="text" aria-label="Search">

Since:

  • 2.1.0



92
93
94
# File 'lib/hanami/view/helpers/tag_helper/tag_builder.rb', line 92

def attributes(**attributes)
  tag_options(**attributes).to_s.strip.html_safe
end

#boolean_tag_option(key) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0



178
179
180
# File 'lib/hanami/view/helpers/tag_helper/tag_builder.rb', line 178

def boolean_tag_option(key)
  %(#{key}="#{key}")
end

#content_tag_string(name, content, **options) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0



119
120
121
122
123
124
125
126
# File 'lib/hanami/view/helpers/tag_helper/tag_builder.rb', line 119

def (name, content, **options)
  tag_options = tag_options(**options) unless options.empty?

  name = EscapeHelper.escape_xml_name(name)
  content = EscapeHelper.escape_html(content)

  "<#{name}#{tag_options}>#{PRE_CONTENT_STRINGS[name]}#{content}</#{name}>".html_safe
end

#p(*args, **options, &block) ⇒ Object

Returns a ‘<p>` HTML tag.

Since:

  • 2.1.0



100
101
102
# File 'lib/hanami/view/helpers/tag_helper/tag_builder.rb', line 100

def p(*args, **options, &block)
  tag_string(:p, *args, **options, &block)
end

#tag_option(key, value) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/hanami/view/helpers/tag_helper/tag_builder.rb', line 184

def tag_option(key, value)
  key = EscapeHelper.escape_xml_name(key)

  case value
  when Array, Hash
    value = TagHelper.build_tag_values(value) if key.to_s == "class"
    value = EscapeHelper.escape_join(value, " ")
  when Regexp
    value = EscapeHelper.escape_html(value.source)
  else
    value = EscapeHelper.escape_html(value)
  end
  value = value.gsub('"', "&quot;") if value.include?('"')

  %(#{key}="#{value}")
end

#tag_options(**options) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0



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
168
169
170
171
172
173
174
# File 'lib/hanami/view/helpers/tag_helper/tag_builder.rb', line 130

def tag_options(**options)
  return if options.none?

  output = +""

  options.each_pair do |key, value|
    type = TAG_TYPES[key]

    if type == :data && value.is_a?(Hash)
      value.each_pair do |k, v|
        next if v.nil?

        output << ATTRIBUTE_SEPARATOR
        output << prefix_tag_option(key, k, v)
      end
    elsif type == :aria && value.is_a?(Hash)
      value.each_pair do |k, v|
        next if v.nil?

        case v
        when Array, Hash
          tokens = TagHelper.build_tag_values(v)
          next if tokens.none?

          v = EscapeHelper.escape_join(tokens, " ")
        else
          v = v.to_s
        end

        output << ATTRIBUTE_SEPARATOR
        output << prefix_tag_option(key, k, v)
      end
    elsif type == :boolean
      if value
        output << ATTRIBUTE_SEPARATOR
        output << boolean_tag_option(key)
      end
    elsif !value.nil?
      output << ATTRIBUTE_SEPARATOR
      output << tag_option(key, value)
    end
  end

  output unless output.empty?
end

#tag_string(name, content = nil, **options) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 2.1.0



106
107
108
109
110
111
112
113
114
115
# File 'lib/hanami/view/helpers/tag_helper/tag_builder.rb', line 106

def tag_string(name, content = nil, **options)
  content = yield if block_given?
  self_closing = SVG_SELF_CLOSING_ELEMENTS.include?(name)

  if (HTML_VOID_ELEMENTS.include?(name) || self_closing) && content.nil?
    "<#{inflector.dasherize(name.to_s)}#{tag_options(**options)}#{self_closing ? " />" : ">"}".html_safe
  else
    (inflector.dasherize(name.to_s), content || "", **options)
  end
end