phlex 1.0.0.rc2 → 1.1.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 +4 -0
- data/README.md +17 -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 +78 -29
- data/lib/phlex/table.rb +7 -9
- data/lib/phlex/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8eeaf45425023ac13320c99f80956f12ec994395b3d349fc6a443334a6715b6d
|
4
|
+
data.tar.gz: 34672ca973f3bec7ade7cccae08e65fff009b122c5319345dadabf779877269e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 51d8f8bea886016a71b67a6b29b1b584dc1a95b29c4ac9cc24263a3e94be534e1ddfa89f800c10caf00618f27508828f9fc1b233b2829d0c1016aa484b0db6fc
|
7
|
+
data.tar.gz: 3cf6631189545652f860ec393fb63cf392bedd326271ee0863238a32f213a4704a7505442d4bbd06c7473e036c0dfb31c1f25584615189d801dc2515a25e4799
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -14,6 +14,12 @@ If you run into any trouble, please [start a discussion](https://github.com/joel
|
|
14
14
|
|
15
15
|
Everyone interacting in Phlex codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/joeldrapper/phlex/blob/main/CODE_OF_CONDUCT.md).
|
16
16
|
|
17
|
+
### Who uses Phlex?
|
18
|
+
|
19
|
+
- [Clearscope](https://www.clearscope.io)
|
20
|
+
|
21
|
+
*If you can share that your company uses Phlex in production, please open a PR to list it here.*
|
22
|
+
|
17
23
|
### Sponsorship 💖
|
18
24
|
|
19
25
|
Maintaining a library is a lot of work. If your company benefits from this work or is likely to benefit from it in the future, please consider [sponsorship](https://github.com/sponsors/joeldrapper). Phlex is actively developed and maintained by **[Joel Drapper](https://github.com/sponsors/joeldrapper)**.
|
@@ -25,3 +31,14 @@ If you’ve found a potential security issue, please email [security@phlex.fun](
|
|
25
31
|
### Thanks 🙏
|
26
32
|
|
27
33
|
Thanks [Logology](https://www.logology.co) for sponsoring our logo.
|
34
|
+
|
35
|
+
### Prior Art 🎨
|
36
|
+
|
37
|
+
- [markaby](https://github.com/markaby/markaby)
|
38
|
+
- [erector](https://github.com/erector/erector)
|
39
|
+
- [papercraft](https://github.com/digital-fabric/papercraft)
|
40
|
+
- [matestack](https://github.com/matestack/matestack-ui-core)
|
41
|
+
- [arbre](https://github.com/activeadmin/arbre)
|
42
|
+
- [tubby](https://github.com/judofyr/tubby)
|
43
|
+
- [hoshi](https://github.com/pete/hoshi)
|
44
|
+
- [hyperstack](https://github.com/hyperstack-org/hyperstack)
|
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
@@ -134,27 +134,39 @@ module Phlex
|
|
134
134
|
end
|
135
135
|
|
136
136
|
def call(buffer = +"", view_context: nil, parent: nil, &block)
|
137
|
-
return buffer unless render?
|
138
|
-
|
139
|
-
raise "The same view instance shouldn't be rendered twice" if rendered?
|
140
|
-
|
141
|
-
@_rendered = true
|
142
137
|
@_target = buffer
|
143
138
|
@_view_context = view_context
|
144
139
|
@_parent = parent
|
145
140
|
|
146
|
-
|
141
|
+
return buffer unless render?
|
147
142
|
|
148
|
-
|
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
|
156
|
+
|
157
|
+
self.class.rendered_at_least_once = true
|
149
158
|
|
150
159
|
buffer
|
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
|
|
@@ -219,8 +224,9 @@ module Phlex
|
|
219
224
|
end
|
220
225
|
|
221
226
|
def unsafe_raw(content = nil, &block)
|
222
|
-
|
223
|
-
|
227
|
+
return nil unless content
|
228
|
+
|
229
|
+
@_target << content
|
224
230
|
end
|
225
231
|
|
226
232
|
def capture(&block)
|
@@ -237,23 +243,30 @@ module Phlex
|
|
237
243
|
new_buffer
|
238
244
|
end
|
239
245
|
|
240
|
-
|
246
|
+
# Default render predicate can be overridden to prevent rendering
|
247
|
+
private def render?
|
248
|
+
true
|
249
|
+
end
|
250
|
+
|
251
|
+
private def format_object(oject)
|
252
|
+
nil
|
253
|
+
end
|
241
254
|
|
242
|
-
def around_template
|
255
|
+
private def around_template
|
243
256
|
before_template
|
244
257
|
yield
|
245
258
|
after_template
|
246
259
|
end
|
247
260
|
|
248
|
-
def before_template
|
261
|
+
private def before_template
|
249
262
|
nil
|
250
263
|
end
|
251
264
|
|
252
|
-
def after_template
|
265
|
+
private def after_template
|
253
266
|
nil
|
254
267
|
end
|
255
268
|
|
256
|
-
def yield_content(&block)
|
269
|
+
private def yield_content(&block)
|
257
270
|
return unless block_given?
|
258
271
|
|
259
272
|
original_length = @_target.length
|
@@ -268,13 +281,42 @@ module Phlex
|
|
268
281
|
@_target << ERB::Util.html_escape(content.name)
|
269
282
|
when Integer, Float
|
270
283
|
@_target << ERB::Util.html_escape(content.to_s)
|
284
|
+
else
|
285
|
+
if (formatted_object = format_object(content))
|
286
|
+
@_target << ERB::Util.html_escape(formatted_object)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
nil
|
292
|
+
end
|
293
|
+
|
294
|
+
private def yield_content_with_args(*args, &block)
|
295
|
+
return unless block_given?
|
296
|
+
|
297
|
+
original_length = @_target.length
|
298
|
+
content = yield(*args)
|
299
|
+
unchanged = (original_length == @_target.length)
|
300
|
+
|
301
|
+
if unchanged
|
302
|
+
case content
|
303
|
+
when String
|
304
|
+
@_target << ERB::Util.html_escape(content)
|
305
|
+
when Symbol
|
306
|
+
@_target << ERB::Util.html_escape(content.name)
|
307
|
+
when Integer, Float
|
308
|
+
@_target << ERB::Util.html_escape(content.to_s)
|
309
|
+
else
|
310
|
+
if (formatted_object = format_object(content))
|
311
|
+
@_target << ERB::Util.html_escape(formatted_object)
|
312
|
+
end
|
271
313
|
end
|
272
314
|
end
|
273
315
|
|
274
316
|
nil
|
275
317
|
end
|
276
318
|
|
277
|
-
def _attributes(**attributes)
|
319
|
+
private def _attributes(**attributes)
|
278
320
|
if attributes[:href]&.start_with?(/\s*javascript/)
|
279
321
|
attributes[:href] = attributes[:href].sub(/^\s*(javascript:)+/, "")
|
280
322
|
end
|
@@ -289,7 +331,7 @@ module Phlex
|
|
289
331
|
buffer
|
290
332
|
end
|
291
333
|
|
292
|
-
def _build_attributes(attributes, buffer:)
|
334
|
+
private def _build_attributes(attributes, buffer:)
|
293
335
|
attributes.each do |k, v|
|
294
336
|
next unless v
|
295
337
|
|
@@ -312,7 +354,14 @@ module Phlex
|
|
312
354
|
when Symbol
|
313
355
|
buffer << " " << name << '="' << ERB::Util.html_escape(v.name) << '"'
|
314
356
|
when Hash
|
315
|
-
_build_attributes(
|
357
|
+
_build_attributes(
|
358
|
+
v.transform_keys { |subkey|
|
359
|
+
case subkey
|
360
|
+
when Symbol then"#{k}-#{subkey.name.tr('_', '-')}"
|
361
|
+
else "#{k}-#{subkey}"
|
362
|
+
end
|
363
|
+
}, buffer: buffer
|
364
|
+
)
|
316
365
|
else
|
317
366
|
buffer << " " << name << '="' << ERB::Util.html_escape(v.to_s) << '"'
|
318
367
|
end
|
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.
|
4
|
+
version: 1.1.0
|
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: 2023-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: zeitwerk
|
@@ -81,9 +81,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
81
81
|
version: '2.7'
|
82
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
83
|
requirements:
|
84
|
-
- - "
|
84
|
+
- - ">="
|
85
85
|
- !ruby/object:Gem::Version
|
86
|
-
version:
|
86
|
+
version: '0'
|
87
87
|
requirements: []
|
88
88
|
rubygems_version: 3.3.25
|
89
89
|
signing_key:
|