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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72f6baa9bd23ce981517a40897f2bb63a1cbd60fbc87bb127883e8eeb36cc302
4
- data.tar.gz: 5abc8c59a81cdff51f5da9250a28d9cc42308b467aa662b155fb1d28eca4a1c2
3
+ metadata.gz: 959fa6b3416f8a2ad94a64379a8b23a1e2693f5990864584694dd8a83e25c03d
4
+ data.tar.gz: 9d7f1f895a8f814c502d8e3b39dc1634710accbcaa7652489186c64b4544d19f
5
5
  SHA512:
6
- metadata.gz: 8db8f9df3da1f218bd2029ea22414ea53a910de8b1810d71c70a0e9022a1353dd69557c91eb1ffee5355733c0d8d6878aae9379a75ee0eaa76d05c6ee20abb8e
7
- data.tar.gz: 8027722c6fd1592c86f5fa6150814206a007c12a810985c72231195dcb0089aa34fd91a5addbeb9c14a8137a5a2f3fe984c07f554ee6504a4b4c25d6dd216046
6
+ metadata.gz: 2aa7a0cc26cee6e3fa2fab8c6fb5072bcb55b8afb3e394491a039dc9243821fc60ebe4d479f2edd00f44d411da8227e4b2d7c3d231ebf08f05cd1fa3bd2c871d
7
+ data.tar.gz: 11ee27a58f2f9a1d5b19b8124648642db6162dd159c060fb6025274a24da28e6fcfb43d2e0e8e889713e658651ea795b07c4835fd9ada80933b1780431555205
data/.rubocop.yml CHANGED
@@ -24,3 +24,7 @@ Style/MethodCallWithoutArgsParentheses:
24
24
 
25
25
  Style/MixinUsage:
26
26
  Enabled: false
27
+
28
+ Style/AccessModifierDeclarations:
29
+ Enabled: true
30
+ EnforcedStyle: inline
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 Vulnerability
3
+ ## Reporting a vulnerability
4
4
 
5
- If you found a possible security vulnerability in Phlex, please email security@phlex.fun.
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.
@@ -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
@@ -2,6 +2,12 @@
2
2
 
3
3
  module Phlex
4
4
  class Configuration
5
- # Config coming soon.
5
+ attr_writer :experimental_warnings
6
+
7
+ def experimental_warnings
8
+ return @experimental_warnings if defined? @experimental_warnings
9
+
10
+ true
11
+ end
6
12
  end
7
13
  end
@@ -3,7 +3,10 @@
3
3
  module Phlex
4
4
  module Experimental
5
5
  def before_template
6
- puts "Warning: #{self.class.name} is experimental and subject to change."
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 { template { yield_content(&block) } }
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
- if renderable.is_a?(Phlex::HTML)
163
+ case renderable
164
+ when Phlex::HTML
155
165
  renderable.call(@_target, view_context: @_view_context, parent: self, &block)
156
- elsif renderable.is_a?(Class) && renderable < Phlex::HTML
157
- raise ArgumentError, "You tried to render the Phlex view class: #{renderable.name} but you probably meant to render an instance of that class instead."
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
- else content.to_s
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
- private
245
+ # Default render predicate can be overridden to prevent rendering
246
+ private def render?
247
+ true
248
+ end
241
249
 
242
- def around_template
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 _attributes(**attributes)
278
- if attributes[:href]&.start_with?(/\s*javascript/)
279
- attributes[:href] = attributes[:href].sub(/^\s*(javascript:)+/, "")
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[name] || name.match?(/[<>&"']/)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Phlex
4
- VERSION = "1.0.0.rc2"
4
+ VERSION = "1.0.1"
5
5
  end
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.0.rc2
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: 2022-11-27 00:00:00.000000000 Z
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: 1.3.1
87
+ version: '0'
87
88
  requirements: []
88
- rubygems_version: 3.3.25
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.