phlex 1.0.0.rc2 → 1.0.1
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 +4 -0
- data/.ruby-version +1 -0
- data/SECURITY.md +10 -2
- data/lib/phlex/collection.rb +1 -3
- data/lib/phlex/configuration.rb +7 -1
- data/lib/phlex/experimental.rb +4 -1
- data/lib/phlex/helpers.rb +4 -4
- data/lib/phlex/html.rb +66 -26
- data/lib/phlex/table.rb +7 -9
- data/lib/phlex/version.rb +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 959fa6b3416f8a2ad94a64379a8b23a1e2693f5990864584694dd8a83e25c03d
|
4
|
+
data.tar.gz: 9d7f1f895a8f814c502d8e3b39dc1634710accbcaa7652489186c64b4544d19f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2aa7a0cc26cee6e3fa2fab8c6fb5072bcb55b8afb3e394491a039dc9243821fc60ebe4d479f2edd00f44d411da8227e4b2d7c3d231ebf08f05cd1fa3bd2c871d
|
7
|
+
data.tar.gz: 11ee27a58f2f9a1d5b19b8124648642db6162dd159c060fb6025274a24da28e6fcfb43d2e0e8e889713e658651ea795b07c4835fd9ada80933b1780431555205
|
data/.rubocop.yml
CHANGED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.3.0
|
data/SECURITY.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Security Policy
|
2
2
|
|
3
|
-
## Reporting a
|
3
|
+
## Reporting a vulnerability
|
4
4
|
|
5
|
-
If you
|
5
|
+
If you find a possible security vulnerability, please email security@phlex.fun. Do not create an issue or pull request either demonstrating or fixing the vulnerability.
|
6
|
+
|
7
|
+
## Bug bounty
|
8
|
+
|
9
|
+
[The Gem Foundation](https://ryanbigg.com/2022/11/the-gem-foundation) has kindly sponsored a $1 bug bounty to discover security vulnerabilities in Phlex.
|
10
|
+
|
11
|
+
## Sponsoring a bug bounty
|
12
|
+
|
13
|
+
If you wish to sponsor a bug bounty for Phlex, please get in touch with Joel at joel@drapper.me.
|
data/lib/phlex/collection.rb
CHANGED
@@ -17,9 +17,7 @@ module Phlex
|
|
17
17
|
@item ? item_template : collection_template { yield_items }
|
18
18
|
end
|
19
19
|
|
20
|
-
private
|
21
|
-
|
22
|
-
def yield_items
|
20
|
+
private def yield_items
|
23
21
|
if @item
|
24
22
|
raise ArgumentError, "You can only yield_items when rendering a collection. You are currently rendering an item."
|
25
23
|
end
|
data/lib/phlex/configuration.rb
CHANGED
data/lib/phlex/experimental.rb
CHANGED
@@ -3,7 +3,10 @@
|
|
3
3
|
module Phlex
|
4
4
|
module Experimental
|
5
5
|
def before_template
|
6
|
-
|
6
|
+
if Phlex.configuration.experimental_warnings
|
7
|
+
puts "Warning: #{self.class.name} is experimental and subject to change."
|
8
|
+
end
|
9
|
+
|
7
10
|
super
|
8
11
|
end
|
9
12
|
end
|
data/lib/phlex/helpers.rb
CHANGED
@@ -5,7 +5,7 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.0")
|
|
5
5
|
end
|
6
6
|
|
7
7
|
module Phlex::Helpers
|
8
|
-
def tokens(*tokens, **conditional_tokens)
|
8
|
+
private def tokens(*tokens, **conditional_tokens)
|
9
9
|
conditional_tokens.each do |condition, token|
|
10
10
|
truthy = case condition
|
11
11
|
when Symbol then send(condition)
|
@@ -28,7 +28,7 @@ module Phlex::Helpers
|
|
28
28
|
tokens.join(" ")
|
29
29
|
end
|
30
30
|
|
31
|
-
def _append_token(tokens, token)
|
31
|
+
private def _append_token(tokens, token)
|
32
32
|
case token
|
33
33
|
when nil then nil
|
34
34
|
when String then tokens << token
|
@@ -39,7 +39,7 @@ module Phlex::Helpers
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
def classes(*tokens, **conditional_tokens)
|
42
|
+
private def classes(*tokens, **conditional_tokens)
|
43
43
|
tokens = self.tokens(*tokens, **conditional_tokens)
|
44
44
|
|
45
45
|
if tokens.empty?
|
@@ -49,7 +49,7 @@ module Phlex::Helpers
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
def mix(*args)
|
52
|
+
private def mix(*args)
|
53
53
|
args.each_with_object({}) do |object, result|
|
54
54
|
result.merge!(object) do |_key, old, new|
|
55
55
|
case new
|
data/lib/phlex/html.rb
CHANGED
@@ -136,14 +136,23 @@ module Phlex
|
|
136
136
|
def call(buffer = +"", view_context: nil, parent: nil, &block)
|
137
137
|
return buffer unless render?
|
138
138
|
|
139
|
-
raise "The same view instance shouldn't be rendered twice" if rendered?
|
140
|
-
|
141
|
-
@_rendered = true
|
142
139
|
@_target = buffer
|
143
140
|
@_view_context = view_context
|
144
141
|
@_parent = parent
|
145
142
|
|
146
|
-
around_template
|
143
|
+
around_template do
|
144
|
+
if block_given?
|
145
|
+
template do |*args|
|
146
|
+
if args.length > 0
|
147
|
+
yield_content_with_args(*args, &block)
|
148
|
+
else
|
149
|
+
yield_content(&block)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
else
|
153
|
+
template
|
154
|
+
end
|
155
|
+
end
|
147
156
|
|
148
157
|
self.class.rendered_at_least_once ||= true
|
149
158
|
|
@@ -151,10 +160,13 @@ module Phlex
|
|
151
160
|
end
|
152
161
|
|
153
162
|
def render(renderable, *args, **kwargs, &block)
|
154
|
-
|
163
|
+
case renderable
|
164
|
+
when Phlex::HTML
|
155
165
|
renderable.call(@_target, view_context: @_view_context, parent: self, &block)
|
156
|
-
|
157
|
-
|
166
|
+
when Class
|
167
|
+
if renderable < Phlex::HTML
|
168
|
+
renderable.new.call(@_target, view_context: @_view_context, parent: self, &block)
|
169
|
+
end
|
158
170
|
else
|
159
171
|
raise ArgumentError, "You can't render a #{renderable}."
|
160
172
|
end
|
@@ -166,14 +178,6 @@ module Phlex
|
|
166
178
|
:html
|
167
179
|
end
|
168
180
|
|
169
|
-
def rendered?
|
170
|
-
@_rendered ||= false
|
171
|
-
end
|
172
|
-
|
173
|
-
def render?
|
174
|
-
true
|
175
|
-
end
|
176
|
-
|
177
181
|
STANDARD_ELEMENTS.each do |method_name, tag|
|
178
182
|
register_element(method_name, tag: tag)
|
179
183
|
end
|
@@ -187,7 +191,8 @@ module Phlex
|
|
187
191
|
case content
|
188
192
|
when String then content
|
189
193
|
when Symbol then content.name
|
190
|
-
|
194
|
+
when Integer, Float then content.to_s
|
195
|
+
else format_object(content) || content.to_s
|
191
196
|
end
|
192
197
|
)
|
193
198
|
|
@@ -237,23 +242,30 @@ module Phlex
|
|
237
242
|
new_buffer
|
238
243
|
end
|
239
244
|
|
240
|
-
|
245
|
+
# Default render predicate can be overridden to prevent rendering
|
246
|
+
private def render?
|
247
|
+
true
|
248
|
+
end
|
241
249
|
|
242
|
-
def
|
250
|
+
private def format_object(oject)
|
251
|
+
nil
|
252
|
+
end
|
253
|
+
|
254
|
+
private def around_template
|
243
255
|
before_template
|
244
256
|
yield
|
245
257
|
after_template
|
246
258
|
end
|
247
259
|
|
248
|
-
def before_template
|
260
|
+
private def before_template
|
249
261
|
nil
|
250
262
|
end
|
251
263
|
|
252
|
-
def after_template
|
264
|
+
private def after_template
|
253
265
|
nil
|
254
266
|
end
|
255
267
|
|
256
|
-
def yield_content(&block)
|
268
|
+
private def yield_content(&block)
|
257
269
|
return unless block_given?
|
258
270
|
|
259
271
|
original_length = @_target.length
|
@@ -268,17 +280,42 @@ module Phlex
|
|
268
280
|
@_target << ERB::Util.html_escape(content.name)
|
269
281
|
when Integer, Float
|
270
282
|
@_target << ERB::Util.html_escape(content.to_s)
|
283
|
+
else
|
284
|
+
if (formatted_object = format_object(content))
|
285
|
+
@_target << ERB::Util.html_escape(formatted_object)
|
286
|
+
end
|
271
287
|
end
|
272
288
|
end
|
273
289
|
|
274
290
|
nil
|
275
291
|
end
|
276
292
|
|
277
|
-
def
|
278
|
-
|
279
|
-
|
293
|
+
private def yield_content_with_args(*args, &block)
|
294
|
+
return unless block_given?
|
295
|
+
|
296
|
+
original_length = @_target.length
|
297
|
+
content = yield(*args)
|
298
|
+
unchanged = (original_length == @_target.length)
|
299
|
+
|
300
|
+
if unchanged
|
301
|
+
case content
|
302
|
+
when String
|
303
|
+
@_target << ERB::Util.html_escape(content)
|
304
|
+
when Symbol
|
305
|
+
@_target << ERB::Util.html_escape(content.name)
|
306
|
+
when Integer, Float
|
307
|
+
@_target << ERB::Util.html_escape(content.to_s)
|
308
|
+
else
|
309
|
+
if (formatted_object = format_object(content))
|
310
|
+
@_target << ERB::Util.html_escape(formatted_object)
|
311
|
+
end
|
312
|
+
end
|
280
313
|
end
|
281
314
|
|
315
|
+
nil
|
316
|
+
end
|
317
|
+
|
318
|
+
private def _attributes(**attributes)
|
282
319
|
buffer = +""
|
283
320
|
_build_attributes(attributes, buffer: buffer)
|
284
321
|
|
@@ -289,7 +326,7 @@ module Phlex
|
|
289
326
|
buffer
|
290
327
|
end
|
291
328
|
|
292
|
-
def _build_attributes(attributes, buffer:)
|
329
|
+
private def _build_attributes(attributes, buffer:)
|
293
330
|
attributes.each do |k, v|
|
294
331
|
next unless v
|
295
332
|
|
@@ -299,8 +336,11 @@ module Phlex
|
|
299
336
|
else k.to_s
|
300
337
|
end
|
301
338
|
|
339
|
+
lower_name = name.downcase
|
340
|
+
next if lower_name == "href" && v.start_with?(/\s*javascript:/i)
|
341
|
+
|
302
342
|
# Detect unsafe attribute names. Attribute names are considered unsafe if they match an event attribute or include unsafe characters.
|
303
|
-
if HTML::EVENT_ATTRIBUTES[
|
343
|
+
if HTML::EVENT_ATTRIBUTES[lower_name] || name.match?(/[<>&"']/)
|
304
344
|
raise ArgumentError, "Unsafe attribute name detected: #{k}."
|
305
345
|
end
|
306
346
|
|
data/lib/phlex/table.rb
CHANGED
@@ -50,13 +50,11 @@ module Phlex
|
|
50
50
|
child.alias_method :foot_cell, :cell
|
51
51
|
end
|
52
52
|
|
53
|
-
private
|
54
|
-
|
55
|
-
def properties
|
53
|
+
private def properties
|
56
54
|
self.class.properties
|
57
55
|
end
|
58
56
|
|
59
|
-
def collection_template(&block)
|
57
|
+
private def collection_template(&block)
|
60
58
|
table do
|
61
59
|
head_template
|
62
60
|
body_template(&block)
|
@@ -64,11 +62,11 @@ module Phlex
|
|
64
62
|
end
|
65
63
|
end
|
66
64
|
|
67
|
-
def item_template
|
65
|
+
private def item_template
|
68
66
|
row_template
|
69
67
|
end
|
70
68
|
|
71
|
-
def head_template
|
69
|
+
private def head_template
|
72
70
|
if self.class.properties.any? { |p| p[:header] }
|
73
71
|
head do
|
74
72
|
head_row do
|
@@ -85,14 +83,14 @@ module Phlex
|
|
85
83
|
end
|
86
84
|
end
|
87
85
|
|
88
|
-
def body_template
|
86
|
+
private def body_template
|
89
87
|
body { yield_items }
|
90
88
|
end
|
91
89
|
|
92
|
-
def foot_template
|
90
|
+
private def foot_template
|
93
91
|
end
|
94
92
|
|
95
|
-
def row_template
|
93
|
+
private def row_template
|
96
94
|
body_row do
|
97
95
|
self.class.properties.each do |property|
|
98
96
|
body_cell(**property[:attributes]) do
|
data/lib/phlex/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: phlex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Drapper
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: zeitwerk
|
@@ -33,6 +33,7 @@ extra_rdoc_files: []
|
|
33
33
|
files:
|
34
34
|
- ".editorconfig"
|
35
35
|
- ".rubocop.yml"
|
36
|
+
- ".ruby-version"
|
36
37
|
- CODE_OF_CONDUCT.md
|
37
38
|
- CONTRIBUTING.md
|
38
39
|
- Gemfile
|
@@ -81,11 +82,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
81
82
|
version: '2.7'
|
82
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
84
|
requirements:
|
84
|
-
- - "
|
85
|
+
- - ">="
|
85
86
|
- !ruby/object:Gem::Version
|
86
|
-
version:
|
87
|
+
version: '0'
|
87
88
|
requirements: []
|
88
|
-
rubygems_version: 3.
|
89
|
+
rubygems_version: 3.5.6
|
89
90
|
signing_key:
|
90
91
|
specification_version: 4
|
91
92
|
summary: A framework for building views in Ruby.
|