html-tag 1.3.2 → 3.0.0

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