phlex 1.3.3 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of phlex might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -24
- data/.ruby-version +1 -1
- data/Gemfile +1 -0
- data/README.md +1 -0
- data/fixtures/view_helper.rb +6 -0
- data/lib/phlex/black_hole.rb +7 -9
- data/lib/phlex/callable.rb +3 -5
- data/lib/phlex/deferred_render.rb +2 -4
- data/lib/phlex/elements.rb +56 -54
- data/lib/phlex/helpers.rb +5 -2
- data/lib/phlex/html/standard_elements.rb +2 -14
- data/lib/phlex/html/void_elements.rb +2 -0
- data/lib/phlex/html.rb +13 -286
- data/lib/{overrides → phlex/overrides}/symbol/name.rb +1 -1
- data/lib/phlex/sgml.rb +315 -0
- data/lib/phlex/svg/standard_elements.rb +391 -0
- data/lib/phlex/svg.rb +11 -0
- data/lib/phlex/testing/view_helper.rb +10 -12
- data/lib/phlex/unbuffered.rb +34 -36
- data/lib/phlex/version.rb +1 -1
- data/lib/phlex.rb +5 -1
- metadata +7 -5
- data/lib/phlex/buffered.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8a6c8dfab161746b6b4e04d403fead1f2477f195ff27e72365838f169ecc287
|
4
|
+
data.tar.gz: e9e9da3414eba5fc53d5440b16c0eecf47d4fc5d09a178fe44c9acab3f554119
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 043c059dd8ce067a50df40c293d61475892acc934a4efdd18bedae7094ebaea3c9dd11a4bc5e5b7779120d38966964a2725dcd17de3dca2de48c50e837e2e8fd
|
7
|
+
data.tar.gz: 00edaf160d669c8f62f40c4f66faf17a6b76b2428648be0d7c7977ad629b119a146cfacffc8636312f87e46b77cdfc3074fe39ade0b4ff45ee10e874f0459a31
|
data/.rubocop.yml
CHANGED
@@ -5,27 +5,5 @@ inherit_from:
|
|
5
5
|
AllCops:
|
6
6
|
TargetRubyVersion: 2.7
|
7
7
|
|
8
|
-
Style/
|
9
|
-
Enabled: false
|
10
|
-
|
11
|
-
Layout/CaseIndentation:
|
12
|
-
Enabled: false
|
13
|
-
|
14
|
-
Style/StringConcatenation:
|
15
|
-
Enabled: false
|
16
|
-
|
17
|
-
Style/CaseEquality:
|
18
|
-
Enabled: false
|
19
|
-
|
20
|
-
Security/Eval:
|
21
|
-
Enabled: false
|
22
|
-
|
23
|
-
Style/MethodCallWithoutArgsParentheses:
|
24
|
-
Enabled: false
|
25
|
-
|
26
|
-
Style/MixinUsage:
|
27
|
-
Enabled: false
|
28
|
-
|
29
|
-
Style/AccessModifierDeclarations:
|
30
|
-
Enabled: true
|
31
|
-
EnforcedStyle: inline
|
8
|
+
Style/ExplicitBlockArgument:
|
9
|
+
Enabled: false
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.2.1
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -43,3 +43,4 @@ Thanks [Logology](https://www.logology.co) for sponsoring our logo.
|
|
43
43
|
- [hoshi](https://github.com/pete/hoshi)
|
44
44
|
- [hyperstack](https://github.com/hyperstack-org/hyperstack)
|
45
45
|
- [clearwater](https://github.com/clearwater-rb/clearwater)
|
46
|
+
- [paggio](https://github.com/opal/paggio)
|
data/fixtures/view_helper.rb
CHANGED
data/lib/phlex/black_hole.rb
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Phlex
|
4
|
-
|
5
|
-
extend self
|
3
|
+
module Phlex::BlackHole
|
4
|
+
extend self
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
def <<(anything)
|
7
|
+
self
|
8
|
+
end
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
end
|
10
|
+
def length
|
11
|
+
0
|
14
12
|
end
|
15
13
|
end
|
data/lib/phlex/callable.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Phlex
|
4
|
-
module
|
5
|
-
# This module doesn't do anything. Phlex::HTML#call checks for its inclusion in the ancestry instead.
|
6
|
-
end
|
3
|
+
module Phlex::DeferredRender
|
4
|
+
# This module doesn't do anything. Phlex::HTML#call checks for its inclusion in the ancestry instead.
|
7
5
|
end
|
data/lib/phlex/elements.rb
CHANGED
@@ -1,61 +1,63 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.0")
|
4
|
-
using Overrides::Symbol::Name
|
4
|
+
using Phlex::Overrides::Symbol::Name
|
5
5
|
end
|
6
6
|
|
7
|
-
module Phlex
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
7
|
+
module Phlex::Elements
|
8
|
+
def register_element(element, tag: element.name.tr("_", "-"))
|
9
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
10
|
+
# frozen_string_literal: true
|
11
|
+
|
12
|
+
def #{element}(**attributes, &block)
|
13
|
+
if attributes.length > 0
|
14
|
+
if block_given?
|
15
|
+
@_target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[attributes.hash] || __attributes__(**attributes)) << ">"
|
16
|
+
yield_content(&block)
|
17
|
+
@_target << "</#{tag}>"
|
18
|
+
else
|
19
|
+
@_target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[attributes.hash] || __attributes__(**attributes)) << "></#{tag}>"
|
20
|
+
end
|
21
|
+
else
|
22
|
+
if block_given?
|
23
|
+
@_target << "<#{tag}>"
|
24
|
+
yield_content(&block)
|
25
|
+
@_target << "</#{tag}>"
|
26
|
+
else
|
27
|
+
@_target << "<#{tag}></#{tag}>"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
alias_method :_#{element}, :#{element}
|
35
|
+
RUBY
|
36
|
+
|
37
|
+
self::REGISTERED_ELEMENTS[element] = tag
|
38
|
+
|
39
|
+
element
|
40
|
+
end
|
41
|
+
|
42
|
+
def register_void_element(element, tag: element.name.tr("_", "-"))
|
43
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
44
|
+
# frozen_string_literal: true
|
45
|
+
|
46
|
+
def #{element}(**attributes)
|
47
|
+
if attributes.length > 0
|
48
|
+
@_target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[attributes.hash] || __attributes__(**attributes)) << ">"
|
49
|
+
else
|
50
|
+
@_target << "<#{tag}>"
|
51
|
+
end
|
52
|
+
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
|
56
|
+
alias_method :_#{element}, :#{element}
|
57
|
+
RUBY
|
58
|
+
|
59
|
+
self::REGISTERED_ELEMENTS[element] = tag
|
60
|
+
|
61
|
+
element
|
60
62
|
end
|
61
63
|
end
|
data/lib/phlex/helpers.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.0")
|
4
|
-
using Overrides::Symbol::Name
|
4
|
+
using Phlex::Overrides::Symbol::Name
|
5
5
|
end
|
6
6
|
|
7
7
|
module Phlex::Helpers
|
@@ -25,7 +25,10 @@ module Phlex::Helpers
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
tokens.join(" ")
|
28
|
+
tokens = tokens.select(&:itself).join(" ")
|
29
|
+
tokens.strip!
|
30
|
+
tokens.gsub!(/\s+/, " ")
|
31
|
+
tokens
|
29
32
|
end
|
30
33
|
|
31
34
|
private def __append_token__(tokens, token)
|
@@ -3,6 +3,8 @@
|
|
3
3
|
module Phlex::HTML::StandardElements
|
4
4
|
extend Phlex::Elements
|
5
5
|
|
6
|
+
REGISTERED_ELEMENTS = Concurrent::Map.new
|
7
|
+
|
6
8
|
# @!method a(**attributes, &content)
|
7
9
|
# Outputs an <code>a</code> tag
|
8
10
|
# @return [nil]
|
@@ -189,13 +191,6 @@ module Phlex::HTML::StandardElements
|
|
189
191
|
# @see https://developer.mozilla.org/docs/Web/HTML/Element/form
|
190
192
|
register_element :form, tag: "form"
|
191
193
|
|
192
|
-
# @!method g(**attributes, &content)
|
193
|
-
# Outputs a <code>g</code> tag
|
194
|
-
# @return [nil]
|
195
|
-
# @see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g
|
196
|
-
# @todo move this to SVG
|
197
|
-
register_element :g, tag: "g"
|
198
|
-
|
199
194
|
# @!method h1(**attributes, &content)
|
200
195
|
# Outputs an <code>h1</code> tag
|
201
196
|
# @return [nil]
|
@@ -377,13 +372,6 @@ module Phlex::HTML::StandardElements
|
|
377
372
|
# @see https://developer.mozilla.org/docs/Web/HTML/Element/p
|
378
373
|
register_element :p, tag: "p"
|
379
374
|
|
380
|
-
# @!method path(**attributes, &content)
|
381
|
-
# Outputs a <code>path</code> tag
|
382
|
-
# @return [nil]
|
383
|
-
# @see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path
|
384
|
-
# @todo move this to SVG
|
385
|
-
register_element :path, tag: "path"
|
386
|
-
|
387
375
|
# @!method picture(**attributes, &content)
|
388
376
|
# Outputs a <code>picture</code> tag
|
389
377
|
# @return [nil]
|
data/lib/phlex/html.rb
CHANGED
@@ -1,47 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.0")
|
4
|
-
using Overrides::Symbol::Name
|
5
|
-
end
|
6
|
-
|
7
3
|
module Phlex
|
8
|
-
class HTML
|
9
|
-
|
10
|
-
|
11
|
-
STANDARD_ELEMENTS = Concurrent::Map.new
|
12
|
-
VOID_ELEMENTS = Concurrent::Map.new
|
13
|
-
|
4
|
+
class HTML < SGML
|
5
|
+
# A list of HTML attributes that have the potential to execute unsafe JavaScript.
|
14
6
|
EVENT_ATTRIBUTES = %w[onabort onafterprint onbeforeprint onbeforeunload onblur oncanplay oncanplaythrough onchange onclick oncontextmenu oncopy oncuechange oncut ondblclick ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop ondurationchange onemptied onended onerror onfocus onhashchange oninput oninvalid onkeydown onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart onmessage onmousedown onmousemove onmouseout onmouseover onmouseup onmousewheel onoffline ononline onpagehide onpageshow onpaste onpause onplay onplaying onpopstate onprogress onratechange onreset onresize onscroll onsearch onseeked onseeking onselect onstalled onstorage onsubmit onsuspend ontimeupdate ontoggle onunload onvolumechange onwaiting onwheel].to_h { [_1, true] }.freeze
|
15
7
|
|
16
8
|
UNBUFFERED_MUTEX = Mutex.new
|
17
9
|
|
18
|
-
extend Elements
|
19
|
-
|
20
|
-
include Helpers
|
21
|
-
include VoidElements
|
22
|
-
include StandardElements
|
23
|
-
|
24
10
|
class << self
|
25
|
-
|
26
|
-
new(...).call
|
27
|
-
end
|
28
|
-
alias_method :render, :call
|
29
|
-
|
30
|
-
def new(*args, **kwargs, &block)
|
31
|
-
if block
|
32
|
-
object = super(*args, **kwargs, &nil)
|
33
|
-
object.instance_variable_set(:@_content_block, block)
|
34
|
-
object
|
35
|
-
else
|
36
|
-
super
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def rendered_at_least_once!
|
41
|
-
alias_method :__attributes__, :__final_attributes__
|
42
|
-
alias_method :call, :__final_call__
|
43
|
-
end
|
44
|
-
|
11
|
+
# @api private
|
45
12
|
def __unbuffered_class__
|
46
13
|
UNBUFFERED_MUTEX.synchronize do
|
47
14
|
if defined? @unbuffered_class
|
@@ -53,268 +20,28 @@ module Phlex
|
|
53
20
|
end
|
54
21
|
end
|
55
22
|
|
56
|
-
|
57
|
-
|
58
|
-
self.class.rendered_at_least_once!
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def __final_call__(buffer = +"", view_context: nil, parent: nil, &block)
|
63
|
-
@_target = buffer
|
64
|
-
@_view_context = view_context
|
65
|
-
@_parent = parent
|
66
|
-
|
67
|
-
block ||= @_content_block
|
68
|
-
|
69
|
-
return buffer unless render?
|
70
|
-
|
71
|
-
around_template do
|
72
|
-
if block
|
73
|
-
if DeferredRender === self
|
74
|
-
__vanish__(self, &block)
|
75
|
-
template
|
76
|
-
else
|
77
|
-
template do |*args|
|
78
|
-
if args.length > 0
|
79
|
-
yield_content_with_args(*args, &block)
|
80
|
-
else
|
81
|
-
yield_content(&block)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
else
|
86
|
-
template
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
buffer
|
91
|
-
end
|
92
|
-
|
93
|
-
def render(renderable, &block)
|
94
|
-
case renderable
|
95
|
-
when Phlex::HTML
|
96
|
-
renderable.call(@_target, view_context: @_view_context, parent: self, &block)
|
97
|
-
when Class
|
98
|
-
if renderable < Phlex::HTML
|
99
|
-
renderable.new.call(@_target, view_context: @_view_context, parent: self, &block)
|
100
|
-
end
|
101
|
-
else
|
102
|
-
raise ArgumentError, "You can't render a #{renderable}."
|
103
|
-
end
|
23
|
+
extend Elements
|
24
|
+
include Helpers, VoidElements, StandardElements
|
104
25
|
|
26
|
+
# Output an HTML doctype.
|
27
|
+
def doctype
|
28
|
+
@_target << "<!DOCTYPE html>"
|
105
29
|
nil
|
106
30
|
end
|
107
31
|
|
108
|
-
def
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
def text(content)
|
113
|
-
@_target << ERB::Util.html_escape(
|
114
|
-
case content
|
115
|
-
when String then content
|
116
|
-
when Symbol then content.name
|
117
|
-
when Integer then content.to_s
|
118
|
-
else format_object(content) || content.to_s
|
32
|
+
def svg(...)
|
33
|
+
super do
|
34
|
+
render Phlex::SVG.new do |svg|
|
35
|
+
yield(svg)
|
119
36
|
end
|
120
|
-
)
|
121
|
-
|
122
|
-
nil
|
123
|
-
end
|
124
|
-
|
125
|
-
def whitespace
|
126
|
-
@_target << " "
|
127
|
-
|
128
|
-
if block_given?
|
129
|
-
yield
|
130
|
-
@_target << " "
|
131
37
|
end
|
132
|
-
|
133
|
-
nil
|
134
|
-
end
|
135
|
-
|
136
|
-
def comment(&block)
|
137
|
-
@_target << "<!-- "
|
138
|
-
yield_content(&block)
|
139
|
-
@_target << " -->"
|
140
|
-
|
141
|
-
nil
|
142
|
-
end
|
143
|
-
|
144
|
-
def doctype
|
145
|
-
@_target << DOCTYPE
|
146
|
-
nil
|
147
|
-
end
|
148
|
-
|
149
|
-
def unsafe_raw(content = nil)
|
150
|
-
return nil unless content
|
151
|
-
|
152
|
-
@_target << content
|
153
|
-
end
|
154
|
-
|
155
|
-
def capture(&block)
|
156
|
-
return unless block_given?
|
157
|
-
|
158
|
-
original_buffer = @_target
|
159
|
-
new_buffer = +""
|
160
|
-
@_target = new_buffer
|
161
|
-
|
162
|
-
yield_content(&block)
|
163
|
-
|
164
|
-
new_buffer
|
165
|
-
ensure
|
166
|
-
@_target = original_buffer
|
167
38
|
end
|
168
39
|
|
40
|
+
# @api private
|
169
41
|
def unbuffered
|
170
42
|
self.class.__unbuffered_class__.new(self)
|
171
43
|
end
|
172
44
|
|
173
|
-
# Like `capture` but the output is vanished into a BlackHole buffer.
|
174
|
-
# Becuase the BlackHole does nothing with the output, this should be faster.
|
175
|
-
private def __vanish__(*args)
|
176
|
-
return unless block_given?
|
177
|
-
|
178
|
-
original_buffer = @_target
|
179
|
-
@_target = BlackHole
|
180
|
-
|
181
|
-
yield(*args)
|
182
|
-
nil
|
183
|
-
ensure
|
184
|
-
@_target = original_buffer
|
185
|
-
end
|
186
|
-
|
187
|
-
# Default render predicate can be overridden to prevent rendering
|
188
|
-
private def render?
|
189
|
-
true
|
190
|
-
end
|
191
|
-
|
192
|
-
private def format_object(object)
|
193
|
-
case object
|
194
|
-
when Float
|
195
|
-
object.to_s
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
private def around_template
|
200
|
-
before_template
|
201
|
-
yield
|
202
|
-
after_template
|
203
|
-
end
|
204
|
-
|
205
|
-
private def before_template
|
206
|
-
nil
|
207
|
-
end
|
208
|
-
|
209
|
-
private def after_template
|
210
|
-
nil
|
211
|
-
end
|
212
|
-
|
213
|
-
private def yield_content
|
214
|
-
return unless block_given?
|
215
|
-
|
216
|
-
original_length = @_target.length
|
217
|
-
content = yield(self)
|
218
|
-
unchanged = (original_length == @_target.length)
|
219
|
-
|
220
|
-
if unchanged
|
221
|
-
case content
|
222
|
-
when String
|
223
|
-
@_target << ERB::Util.html_escape(content)
|
224
|
-
when Symbol
|
225
|
-
@_target << ERB::Util.html_escape(content.name)
|
226
|
-
when Integer
|
227
|
-
@_target << ERB::Util.html_escape(content.to_s)
|
228
|
-
else
|
229
|
-
if (formatted_object = format_object(content))
|
230
|
-
@_target << ERB::Util.html_escape(formatted_object)
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
nil
|
236
|
-
end
|
237
|
-
|
238
|
-
private def yield_content_with_args(*args)
|
239
|
-
return unless block_given?
|
240
|
-
|
241
|
-
original_length = @_target.length
|
242
|
-
content = yield(*args)
|
243
|
-
unchanged = (original_length == @_target.length)
|
244
|
-
|
245
|
-
if unchanged
|
246
|
-
case content
|
247
|
-
when String
|
248
|
-
@_target << ERB::Util.html_escape(content)
|
249
|
-
when Symbol
|
250
|
-
@_target << ERB::Util.html_escape(content.name)
|
251
|
-
when Integer, Float
|
252
|
-
@_target << ERB::Util.html_escape(content.to_s)
|
253
|
-
else
|
254
|
-
if (formatted_object = format_object(content))
|
255
|
-
@_target << ERB::Util.html_escape(formatted_object)
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
nil
|
261
|
-
end
|
262
|
-
|
263
|
-
private def __attributes__(**attributes)
|
264
|
-
__final_attributes__(**attributes).tap do |buffer|
|
265
|
-
Phlex::ATTRIBUTE_CACHE[attributes.hash] = buffer.freeze
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
private def __final_attributes__(**attributes)
|
270
|
-
buffer = +""
|
271
|
-
__build_attributes__(attributes, buffer: buffer)
|
272
|
-
|
273
|
-
buffer
|
274
|
-
end
|
275
|
-
|
276
|
-
private def __build_attributes__(attributes, buffer:)
|
277
|
-
attributes.each do |k, v|
|
278
|
-
next unless v
|
279
|
-
|
280
|
-
name = case k
|
281
|
-
when String then k
|
282
|
-
when Symbol then k.name.tr("_", "-")
|
283
|
-
else k.to_s
|
284
|
-
end
|
285
|
-
|
286
|
-
lower_name = name.downcase
|
287
|
-
next if lower_name == "href" && v.start_with?(/\s*javascript:/i)
|
288
|
-
|
289
|
-
# Detect unsafe attribute names. Attribute names are considered unsafe if they match an event attribute or include unsafe characters.
|
290
|
-
if HTML::EVENT_ATTRIBUTES[lower_name] || name.match?(/[<>&"']/)
|
291
|
-
raise ArgumentError, "Unsafe attribute name detected: #{k}."
|
292
|
-
end
|
293
|
-
|
294
|
-
case v
|
295
|
-
when true
|
296
|
-
buffer << " " << name
|
297
|
-
when String
|
298
|
-
buffer << " " << name << '="' << ERB::Util.html_escape(v) << '"'
|
299
|
-
when Symbol
|
300
|
-
buffer << " " << name << '="' << ERB::Util.html_escape(v.name) << '"'
|
301
|
-
when Hash
|
302
|
-
__build_attributes__(
|
303
|
-
v.transform_keys { |subkey|
|
304
|
-
case subkey
|
305
|
-
when Symbol then"#{k}-#{subkey.name.tr('_', '-')}"
|
306
|
-
else "#{k}-#{subkey}"
|
307
|
-
end
|
308
|
-
}, buffer: buffer
|
309
|
-
)
|
310
|
-
else
|
311
|
-
buffer << " " << name << '="' << ERB::Util.html_escape(v.to_s) << '"'
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
|
-
buffer
|
316
|
-
end
|
317
|
-
|
318
45
|
# This should be the last method defined
|
319
46
|
def self.method_added(method_name)
|
320
47
|
if method_name[0] == "_" && Phlex::HTML.instance_methods.include?(method_name) && instance_method(method_name).owner != Phlex::HTML
|