html-tag 2.0.0 → 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: 5c14a5d669505ed74d43e52cb564a8635a48a21670e0dce86756b3fc18a90a28
4
- data.tar.gz: 00c996b4444863bd710c722585b53638a28f562e64a79483335a853a7e4670e0
3
+ metadata.gz: 1af81083a15e78d8cecfed801fb466ce389ccae3bd5378528acc1f63aa345e3a
4
+ data.tar.gz: 668a8a601339fe419daba93f97c33df6f4d3c1ce391b6df6cb70d3cb5574f719
5
5
  SHA512:
6
- metadata.gz: 00eebf82a2b96e95f25272f536ada28d90115a2a177a129c5877a966449dc87de88833520eb9aa0e8d18038f06a9fd3bab079e10ae92c40be3479e4670787592
7
- data.tar.gz: 57047fe46f74f6bb2e6d400c1c0bbb4e9832fc631eabc43cd4f83070c7ccfa67d2a87c6a6c62e1b44db73d61ed3ce2b1fc17412f6a461616f37c349fc759b9b2
6
+ metadata.gz: d520970b6bfbeb1738e7dc23110f4c66e3859a98fbeb59876f9d31bd916f1b288bb72743da4b38bc944942880d92c4641cce873e1e8e57f82ac726dafacdacfa
7
+ data.tar.gz: fd4750d1cdbfe778a41a02371a3cca980956ec553acf66df3daf5b40a73c3249e22aceab0287e6f0ca3760da46d71befeb7d029d696d847abd786504bf1ada0a
data/.version CHANGED
@@ -1 +1 @@
1
- 2.0.0
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
@@ -1,18 +1,38 @@
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
- def tag
7
- ::HtmlTagBuilder
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
8
28
  end
9
29
 
10
30
  # forward to class only if
11
31
  def method_missing tag_name, *args, &block
12
32
  if self === HtmlTag
13
- ::HtmlTagBuilder.tag(tag_name, args[0], args[1], &block)
33
+ Outbound.tag(tag_name, args[0], args[1], &block)
14
34
  else
15
35
  super
16
36
  end
17
37
  end
18
- 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,3 +1,5 @@
1
- require_relative './html-tag/html_tag_builder'
2
1
  require_relative './html-tag/html_tag'
3
- require_relative './html-tag/adapter'
2
+ require_relative './html-tag/outbound'
3
+ require_relative './html-tag/inbound'
4
+ require_relative './html-tag/globals'
5
+
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: 2.0.0
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-27 00:00:00.000000000 Z
11
+ date: 2022-07-29 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,10 @@ extra_rdoc_files: []
19
19
  files:
20
20
  - "./.version"
21
21
  - "./lib/html-tag.rb"
22
- - "./lib/html-tag/adapter.rb"
22
+ - "./lib/html-tag/globals.rb"
23
23
  - "./lib/html-tag/html_tag.rb"
24
- - "./lib/html-tag/html_tag_builder.rb"
24
+ - "./lib/html-tag/inbound.rb"
25
+ - "./lib/html-tag/outbound.rb"
25
26
  homepage: https://github.com/dux/html-tag
26
27
  licenses:
27
28
  - MIT
@@ -41,7 +42,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
41
42
  - !ruby/object:Gem::Version
42
43
  version: '0'
43
44
  requirements: []
44
- rubygems_version: 3.0.6
45
+ rubygems_version: 3.2.3
45
46
  signing_key:
46
47
  specification_version: 4
47
48
  summary: HTML tag builder
@@ -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(/"/,'&quot;')+'"'
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