html-tag 2.0.0 → 3.0.3
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.
- checksums.yaml +4 -4
- data/.version +1 -1
- data/lib/html-tag/globals.rb +51 -0
- data/lib/html-tag/html_tag.rb +13 -4
- data/lib/html-tag/inbound.rb +212 -0
- data/lib/html-tag.rb +3 -2
- metadata +5 -5
- data/lib/html-tag/adapter.rb +0 -17
- data/lib/html-tag/html_tag_builder.rb +0 -124
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 371d71aa213375cfe4bbdcddc096f98b456c394e566d7c848479ae515f5848ea
         | 
| 4 | 
            +
              data.tar.gz: 7dc7321d44062b12aa20beb91595f215af56d088493486b92c81b68e2b27c764
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 81e54a74195a0b92fbd04753b05990c4f0f88db1dc7c229cb44a4f967c69b2f111011b206cb1f841be21e2993f26e5af3e7592050fa9883a9d87ff132f86dac9
         | 
| 7 | 
            +
              data.tar.gz: 177f240dfd9524e1adacac728f469648b4610ab8bb87daff2862d1e11d3121110caf59d5725416e40a7780bad4ed1d9b34d0265dab6431526c9d9b3341b020e4
         | 
    
        data/.version
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            3.0.3
         | 
| @@ -0,0 +1,51 @@ | |
| 1 | 
            +
            # Hash
         | 
| 2 | 
            +
            unless {}.respond_to?(:tag)
         | 
| 3 | 
            +
              class Hash
         | 
| 4 | 
            +
                def tag node_name, inner_html=nil, &block
         | 
| 5 | 
            +
                  HtmlTag::Inbound.new.tag(node_name, inner_html, self, &block).join('')
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
            end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            # String
         | 
| 11 | 
            +
            unless ''.respond_to?(:tag)
         | 
| 12 | 
            +
              class String
         | 
| 13 | 
            +
                def tag node_name, opts = nil, &block
         | 
| 14 | 
            +
                  HtmlTag::Inbound.new.tag(node_name, self, opts, &block).join('')
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            # HtmlTag do ...
         | 
| 20 | 
            +
            module HtmlTag
         | 
| 21 | 
            +
              class Proxy
         | 
| 22 | 
            +
                def initialize scope = nil
         | 
| 23 | 
            +
                  @pointer = HtmlTag::Inbound.new scope
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def method_missing name, *args, &block
         | 
| 27 | 
            +
                  @pointer
         | 
| 28 | 
            +
                    .send(name, *args, &block)
         | 
| 29 | 
            +
                    .join('')
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            def HtmlTag *args, &block
         | 
| 35 | 
            +
              args[0] ||= :div
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              if args[0].class == Hash
         | 
| 38 | 
            +
                args[1] = args[0]
         | 
| 39 | 
            +
                args[0] = :div
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              if block
         | 
| 43 | 
            +
                # HtmlTag(:ul) { li ... }
         | 
| 44 | 
            +
                out = HtmlTag::Inbound.new self
         | 
| 45 | 
            +
                out.send(*args, &block)
         | 
| 46 | 
            +
                out.render
         | 
| 47 | 
            +
              else
         | 
| 48 | 
            +
                # HtmlTag._foo 123
         | 
| 49 | 
            +
                HtmlTag::Proxy.new self
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
            end
         | 
    
        data/lib/html-tag/html_tag.rb
    CHANGED
    
    | @@ -1,18 +1,27 @@ | |
| 1 1 | 
             
            # inclue HtmlTag to import tag method
         | 
| 2 2 |  | 
| 3 | 
            +
            require 'set'
         | 
| 4 | 
            +
             | 
| 3 5 | 
             
            module HtmlTag
         | 
| 4 6 | 
             
              extend self
         | 
| 5 7 |  | 
| 6 | 
            -
               | 
| 7 | 
            -
             | 
| 8 | 
            +
              ###
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              OPTS = {
         | 
| 11 | 
            +
                format: false
         | 
| 12 | 
            +
              }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              def tag *args, &block
         | 
| 15 | 
            +
                HtmlTag *args, &block
         | 
| 8 16 | 
             
              end
         | 
| 9 17 |  | 
| 10 18 | 
             
              # forward to class only if
         | 
| 11 19 | 
             
              def method_missing tag_name, *args, &block
         | 
| 12 20 | 
             
                if self === HtmlTag
         | 
| 13 | 
            -
                   | 
| 21 | 
            +
                  # Outbound.tag(tag_name, args[0], args[1], &block)
         | 
| 22 | 
            +
                  Proxy.new.tag(tag_name, args[0], args[1], &block)
         | 
| 14 23 | 
             
                else
         | 
| 15 24 | 
             
                  super
         | 
| 16 25 | 
             
                end
         | 
| 17 26 | 
             
              end
         | 
| 18 | 
            -
            end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,212 @@ | |
| 1 | 
            +
            # improved HTML builder that doess not need node pointers
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module HtmlTag
         | 
| 4 | 
            +
              class Inbound
         | 
| 5 | 
            +
                IVARS ||= Struct.new :HtmlTagInboundIvars, :context, :data, :depth
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                TAGS ||= Set.new %i(
         | 
| 8 | 
            +
                  a article b button code center colgroup dd div dl dt em fieldset form h1 h2 h3 h4 h5 h6
         | 
| 9 | 
            +
                  header i iframe label legend li main map nav noscript object ol optgroup option p pre q
         | 
| 10 | 
            +
                  script section select small span sub strong style summary table tbody td textarea tfoot th thead title tr u ul video
         | 
| 11 | 
            +
                )
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                EMPTY_TAGS ||= Set.new %w(area base br col embed hr img input keygen link meta param source track wbr)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                # allows to add cusom tags if needed
         | 
| 16 | 
            +
                # HtmlTag::Inbound.define :foo
         | 
| 17 | 
            +
                def self.define name, empty: false
         | 
| 18 | 
            +
                  if empty
         | 
| 19 | 
            +
                    EMPTY_TAGS.add name
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  define_method name do |*args, &block|
         | 
| 23 | 
            +
                    tag name, *args, &block
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                # create static methods for all common tags (method missing is slow)
         | 
| 28 | 
            +
                (TAGS + EMPTY_TAGS).each {|tag| define tag }
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                ###
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def initialize context = nil
         | 
| 33 | 
            +
                  # copy all instance varialbes from context
         | 
| 34 | 
            +
                  for el in context.instance_variables
         | 
| 35 | 
            +
                    unless el.to_s.include?('@_')
         | 
| 36 | 
            +
                      val = context.instance_variable_get el
         | 
| 37 | 
            +
                      instance_variable_set el, val
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  # lets keep all instance vars in one object
         | 
| 42 | 
            +
                  @_iv = IVARS.new
         | 
| 43 | 
            +
                  @_iv.context = context
         | 
| 44 | 
            +
                  @_iv.data    = []
         | 
| 45 | 
            +
                  @_iv.depth   = 0
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                # access parent context via parent / context / this
         | 
| 49 | 
            +
                # h1 class: this.class_name
         | 
| 50 | 
            +
                def parent &block
         | 
| 51 | 
            +
                  unless @_iv.context
         | 
| 52 | 
            +
                    raise 'Host scope is not available'
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  if block
         | 
| 56 | 
            +
                    @_iv.context.instance_exec(&block)
         | 
| 57 | 
            +
                  else
         | 
| 58 | 
            +
                    @_iv.context
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
                alias :context :parent
         | 
| 62 | 
            +
                alias :this :parent
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                # export renderd data
         | 
| 65 | 
            +
                def render
         | 
| 66 | 
            +
                  @_iv.data
         | 
| 67 | 
            +
                    .join('')
         | 
| 68 | 
            +
                    .gsub(/\n+/, $/)
         | 
| 69 | 
            +
                    #.gsub(/([\w>])[[:blank:]]+</, '\1<')
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                # render single node
         | 
| 73 | 
            +
                def tag name, *args, &block
         | 
| 74 | 
            +
                  name, opt_hash, opt_data = _prepare_tag_params name, args
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  tag_data = "%s%s<%s" % [_depth_new_line, _depth_spaces, name]
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                  # if tag params given, add them
         | 
| 79 | 
            +
                  if opt_hash
         | 
| 80 | 
            +
                    tag_data += ' '
         | 
| 81 | 
            +
                    tag_data += opt_hash.inject([]) do |t, el|
         | 
| 82 | 
            +
                      key, value = el
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                      if value.class == Hash
         | 
| 85 | 
            +
                        for el in value
         | 
| 86 | 
            +
                          t.push "%s-%s='%s'" % [key, el[0], _escape_param(el[1])]
         | 
| 87 | 
            +
                        end
         | 
| 88 | 
            +
                      else
         | 
| 89 | 
            +
                        if value.class == Array
         | 
| 90 | 
            +
                          value = value.join(' ')
         | 
| 91 | 
            +
                        end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                        key = key.to_s.sub(/^data_/, 'data-')
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                        t.push "%s='%s'" % [key, _escape_param(value)]
         | 
| 96 | 
            +
                      end
         | 
| 97 | 
            +
                      t
         | 
| 98 | 
            +
                    end.join(' ')
         | 
| 99 | 
            +
                  end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                  unless EMPTY_TAGS.include?(name)
         | 
| 102 | 
            +
                    tag_data += '>'
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                  @_iv.data << tag_data
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  # nested blocks
         | 
| 108 | 
            +
                  if block
         | 
| 109 | 
            +
                    @_iv.depth += 1
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                    block_data = if @_iv.context
         | 
| 112 | 
            +
                      # HtmlTag scope
         | 
| 113 | 
            +
                      instance_exec(self, &block)
         | 
| 114 | 
            +
                    else
         | 
| 115 | 
            +
                      # outbound scope
         | 
| 116 | 
            +
                      block.call(self)
         | 
| 117 | 
            +
                    end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                    if block_data.class == String
         | 
| 120 | 
            +
                      @_iv.data << block_data
         | 
| 121 | 
            +
                    end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                    @_iv.depth -= 1
         | 
| 124 | 
            +
                  end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                  if EMPTY_TAGS.include?(name)
         | 
| 127 | 
            +
                    @_iv.data << ' />'
         | 
| 128 | 
            +
                  else
         | 
| 129 | 
            +
                    unless opt_data
         | 
| 130 | 
            +
                      @_iv.data << _depth_spaces
         | 
| 131 | 
            +
                    end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                    if opt_data.class == Array
         | 
| 134 | 
            +
                      opt_data = opt_data.join('')\
         | 
| 135 | 
            +
                    end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                    @_iv.data << '%s</%s>%s' % [opt_data, name, _depth_new_line]
         | 
| 138 | 
            +
                  end
         | 
| 139 | 
            +
                end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                def push data = nil
         | 
| 142 | 
            +
                  if block_given?
         | 
| 143 | 
            +
                    data = yield
         | 
| 144 | 
            +
                  end
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                  @_iv.data << data
         | 
| 147 | 
            +
                end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                def method_missing name, *args, &block
         | 
| 150 | 
            +
                  klass = name.to_s
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                  if klass.start_with?('_')
         | 
| 153 | 
            +
                    tag klass, *args, &block
         | 
| 154 | 
            +
                  elsif @_iv.context
         | 
| 155 | 
            +
                    @_iv.context.send name, *args, &block
         | 
| 156 | 
            +
                  else
         | 
| 157 | 
            +
                    message = [
         | 
| 158 | 
            +
                      %{HTML tag "#{name}" not found.},
         | 
| 159 | 
            +
                      "Use this.#{name}() to call method in parent context",
         | 
| 160 | 
            +
                      "or use tag(:#{name}, params, data) to add custom html node."
         | 
| 161 | 
            +
                    ]
         | 
| 162 | 
            +
                    raise NoMethodError.new(message.join(' '))
         | 
| 163 | 
            +
                  end
         | 
| 164 | 
            +
                end
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                private
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                def _prepare_tag_params name, args
         | 
| 169 | 
            +
                  opt_hash, opt_data = args
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                  # allow any arragement of vars
         | 
| 172 | 
            +
                  # div class: :foo, 123
         | 
| 173 | 
            +
                  # div 123, class: :foo
         | 
| 174 | 
            +
                  if opt_data.class == Hash || (opt_hash && opt_hash.class != Hash)
         | 
| 175 | 
            +
                    opt_hash, opt_data = opt_data, opt_hash
         | 
| 176 | 
            +
                  end
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                  # _foo__bar-baz class: 'dux' ->  <div class="foo bar-baz dux"></div>
         | 
| 179 | 
            +
                  klass = name.to_s
         | 
| 180 | 
            +
                  if klass.start_with?('_')
         | 
| 181 | 
            +
                    classes = klass
         | 
| 182 | 
            +
                      .sub('_', '')
         | 
| 183 | 
            +
                      .split('__')
         | 
| 184 | 
            +
                      .map{|it| it.gsub('_', '-') }
         | 
| 185 | 
            +
                      .join(' ')
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                    klass = :div
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                    opt_hash ||= {}
         | 
| 190 | 
            +
                    opt_hash[:class] = "#{classes} #{opt_hash[:class]}".sub(/\s+$/, '')
         | 
| 191 | 
            +
                  end
         | 
| 192 | 
            +
             | 
| 193 | 
            +
                  [klass, opt_hash, opt_data]
         | 
| 194 | 
            +
                end
         | 
| 195 | 
            +
             | 
| 196 | 
            +
                def _depth_spaces
         | 
| 197 | 
            +
                  if OPTS[:format]
         | 
| 198 | 
            +
                    ' ' * 2 * @_iv.depth
         | 
| 199 | 
            +
                  else
         | 
| 200 | 
            +
                    ''
         | 
| 201 | 
            +
                  end
         | 
| 202 | 
            +
                end
         | 
| 203 | 
            +
             | 
| 204 | 
            +
                def _depth_new_line
         | 
| 205 | 
            +
                  OPTS[:format] ? $/ : ''
         | 
| 206 | 
            +
                end
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                def _escape_param el
         | 
| 209 | 
            +
                  el.to_s.gsub(/'/, ''')
         | 
| 210 | 
            +
                end
         | 
| 211 | 
            +
              end
         | 
| 212 | 
            +
            end
         | 
    
        data/lib/html-tag.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: html-tag
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version:  | 
| 4 | 
            +
              version: 3.0.3
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Dino Reic
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2022-07-30 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies: []
         | 
| 13 13 | 
             
            description: Fast and powerful tag builder, upgrade to Rails tag helper, framework
         | 
| 14 14 | 
             
              agnostic.
         | 
| @@ -19,9 +19,9 @@ extra_rdoc_files: [] | |
| 19 19 | 
             
            files:
         | 
| 20 20 | 
             
            - "./.version"
         | 
| 21 21 | 
             
            - "./lib/html-tag.rb"
         | 
| 22 | 
            -
            - "./lib/html-tag/ | 
| 22 | 
            +
            - "./lib/html-tag/globals.rb"
         | 
| 23 23 | 
             
            - "./lib/html-tag/html_tag.rb"
         | 
| 24 | 
            -
            - "./lib/html-tag/ | 
| 24 | 
            +
            - "./lib/html-tag/inbound.rb"
         | 
| 25 25 | 
             
            homepage: https://github.com/dux/html-tag
         | 
| 26 26 | 
             
            licenses:
         | 
| 27 27 | 
             
            - MIT
         | 
| @@ -41,7 +41,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 41 41 | 
             
                - !ruby/object:Gem::Version
         | 
| 42 42 | 
             
                  version: '0'
         | 
| 43 43 | 
             
            requirements: []
         | 
| 44 | 
            -
            rubygems_version: 3. | 
| 44 | 
            +
            rubygems_version: 3.2.3
         | 
| 45 45 | 
             
            signing_key:
         | 
| 46 46 | 
             
            specification_version: 4
         | 
| 47 47 | 
             
            summary: HTML tag builder
         | 
    
        data/lib/html-tag/adapter.rb
    DELETED
    
    | @@ -1,17 +0,0 @@ | |
| 1 | 
            -
            # Hash
         | 
| 2 | 
            -
            unless {}.respond_to?(:tag)
         | 
| 3 | 
            -
              class Hash
         | 
| 4 | 
            -
                def tag node_name, inner_html=nil
         | 
| 5 | 
            -
                  ::HtmlTagBuilder.build node_name, self, inner_html
         | 
| 6 | 
            -
                end
         | 
| 7 | 
            -
              end
         | 
| 8 | 
            -
            end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
            # String
         | 
| 11 | 
            -
            unless ''.respond_to?(:tag)
         | 
| 12 | 
            -
              class String
         | 
| 13 | 
            -
                def tag node_name, opts={}
         | 
| 14 | 
            -
                  ::HtmlTagBuilder.build node_name, opts, self
         | 
| 15 | 
            -
                end
         | 
| 16 | 
            -
              end
         | 
| 17 | 
            -
            end
         | 
| @@ -1,124 +0,0 @@ | |
| 1 | 
            -
            require 'set'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            class HtmlTagBuilder
         | 
| 4 | 
            -
              EMPTY_TAGS ||= Set.new %w(area base br col embed hr img input keygen link meta param source track wbr)
         | 
| 5 | 
            -
             | 
| 6 | 
            -
              class << self
         | 
| 7 | 
            -
                # tag.div -> tag.tag :div
         | 
| 8 | 
            -
                def method_missing name, *args, &block
         | 
| 9 | 
            -
                  tag name, args[0], args[1], &block
         | 
| 10 | 
            -
                end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                # tag :div, { 'class'=>'iform' } do
         | 
| 13 | 
            -
                def tag name, *args
         | 
| 14 | 
            -
                  data, opts =
         | 
| 15 | 
            -
                  if args[1]
         | 
| 16 | 
            -
                    args[0].class == Hash ? args.reverse : args
         | 
| 17 | 
            -
                  elsif args[0]
         | 
| 18 | 
            -
                    if args[0].class == Symbol
         | 
| 19 | 
            -
                      # tag.div(:a) { 1 } -> <div class="a">1</div>
         | 
| 20 | 
            -
                      [nil, { class: args[0].to_s.gsub('__', ' ').gsub('_', '-') }]
         | 
| 21 | 
            -
                    elsif args[0].class == Hash
         | 
| 22 | 
            -
                      [nil, args[0]]
         | 
| 23 | 
            -
                    else
         | 
| 24 | 
            -
                      [args[0], {}]
         | 
| 25 | 
            -
                    end
         | 
| 26 | 
            -
                  else
         | 
| 27 | 
            -
                    [nil, {}]
         | 
| 28 | 
            -
                  end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                  opts ||= {}
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                  unless opts.class == Hash
         | 
| 33 | 
            -
                    raise ArgumentError.new('HtmlTag: bad agrument, attriobutes are no a hash')
         | 
| 34 | 
            -
                  end
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                  if data.class == Hash
         | 
| 37 | 
            -
                    raise ArgumentError.new('HtmlTag: bad agrument, data sent as hash')
         | 
| 38 | 
            -
                  end
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                  # covert n._row_foo to n(class: 'row-foo')
         | 
| 41 | 
            -
                  name = name.to_s
         | 
| 42 | 
            -
                  if name.to_s[0, 1] == '_'
         | 
| 43 | 
            -
                    opts ||= {}
         | 
| 44 | 
            -
                    opts[:class] = name.to_s.sub('_', '').gsub('_', '-')
         | 
| 45 | 
            -
                    name = :div
         | 
| 46 | 
            -
                  end
         | 
| 47 | 
            -
             | 
| 48 | 
            -
                  if block_given?
         | 
| 49 | 
            -
                    if data
         | 
| 50 | 
            -
                      raise ArgumentError.new('HtmlTag: data is allreay defined and block is given')
         | 
| 51 | 
            -
                    end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                    stack = new
         | 
| 54 | 
            -
                    data  = yield(stack, opts)
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                    # if data is pushed to passed node, use that data
         | 
| 57 | 
            -
                    data = stack.data if stack.data.first
         | 
| 58 | 
            -
                  end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                  data = data.join('') if data.is_a?(Array)
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                  build name, opts, data
         | 
| 63 | 
            -
                end
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                # build html node
         | 
| 66 | 
            -
                def build node, attrs={}, text=nil
         | 
| 67 | 
            -
                  node = node.to_s
         | 
| 68 | 
            -
             | 
| 69 | 
            -
                  opts = []
         | 
| 70 | 
            -
                  attrs.each do |attr_key, attr_value|
         | 
| 71 | 
            -
                    if attr_value.is_a?(Hash)
         | 
| 72 | 
            -
                      for data_key, data_value in attr_value
         | 
| 73 | 
            -
                        __add_opts opts, "#{attr_key}-#{data_key}", data_value
         | 
| 74 | 
            -
                      end
         | 
| 75 | 
            -
                    else
         | 
| 76 | 
            -
                      __add_opts opts, attr_key, attr_value
         | 
| 77 | 
            -
                    end
         | 
| 78 | 
            -
                  end
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                  opts = opts.first ? ' '+opts.join(' ') : ''
         | 
| 81 | 
            -
             | 
| 82 | 
            -
                  if node
         | 
| 83 | 
            -
                    text ||= '' unless EMPTY_TAGS.include?(node)
         | 
| 84 | 
            -
                    out = text ? %{<#{node}#{opts}>#{text}</#{node}>} : %{<#{node}#{opts} />}
         | 
| 85 | 
            -
                    out.respond_to?(:html_safe) ? out.html_safe : out
         | 
| 86 | 
            -
                  else
         | 
| 87 | 
            -
                    opts
         | 
| 88 | 
            -
                  end
         | 
| 89 | 
            -
                end
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                # tag.div(class: 'klasa') do -> tag.('klasa') do
         | 
| 92 | 
            -
                def call class_name, &block
         | 
| 93 | 
            -
                  tag(:div, class_name, &block)
         | 
| 94 | 
            -
                end
         | 
| 95 | 
            -
             | 
| 96 | 
            -
                def __add_opts opts, key, value
         | 
| 97 | 
            -
                  unless value.to_s == ''
         | 
| 98 | 
            -
                    value = value.join(' ') if value.is_a?(Array)
         | 
| 99 | 
            -
                    key   = key.to_s.gsub(/data_/,'data-')
         | 
| 100 | 
            -
                    opts.push key+'="'+value.to_s.gsub(/"/,'"')+'"'
         | 
| 101 | 
            -
                  end
         | 
| 102 | 
            -
                end
         | 
| 103 | 
            -
              end
         | 
| 104 | 
            -
             | 
| 105 | 
            -
              ###
         | 
| 106 | 
            -
             | 
| 107 | 
            -
              attr_reader :data
         | 
| 108 | 
            -
             | 
| 109 | 
            -
              def initialize
         | 
| 110 | 
            -
                @data = []
         | 
| 111 | 
            -
              end
         | 
| 112 | 
            -
             | 
| 113 | 
            -
              # push data to stack
         | 
| 114 | 
            -
              def push data=nil
         | 
| 115 | 
            -
                @data.push block_given? ? yield : data
         | 
| 116 | 
            -
              end
         | 
| 117 | 
            -
             | 
| 118 | 
            -
              private
         | 
| 119 | 
            -
             | 
| 120 | 
            -
              # forward to class
         | 
| 121 | 
            -
              def method_missing tag_name, *args, &block
         | 
| 122 | 
            -
                @data.push self.class.tag(tag_name, args[0], args[1], &block)
         | 
| 123 | 
            -
              end
         | 
| 124 | 
            -
            end
         |