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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72f6baa9bd23ce981517a40897f2bb63a1cbd60fbc87bb127883e8eeb36cc302
4
- data.tar.gz: 5abc8c59a81cdff51f5da9250a28d9cc42308b467aa662b155fb1d28eca4a1c2
3
+ metadata.gz: 8eeaf45425023ac13320c99f80956f12ec994395b3d349fc6a443334a6715b6d
4
+ data.tar.gz: 34672ca973f3bec7ade7cccae08e65fff009b122c5319345dadabf779877269e
5
5
  SHA512:
6
- metadata.gz: 8db8f9df3da1f218bd2029ea22414ea53a910de8b1810d71c70a0e9022a1353dd69557c91eb1ffee5355733c0d8d6878aae9379a75ee0eaa76d05c6ee20abb8e
7
- data.tar.gz: 8027722c6fd1592c86f5fa6150814206a007c12a810985c72231195dcb0089aa34fd91a5addbeb9c14a8137a5a2f3fe984c07f554ee6504a4b4c25d6dd216046
6
+ metadata.gz: 51d8f8bea886016a71b67a6b29b1b584dc1a95b29c4ac9cc24263a3e94be534e1ddfa89f800c10caf00618f27508828f9fc1b233b2829d0c1016aa484b0db6fc
7
+ data.tar.gz: 3cf6631189545652f860ec393fb63cf392bedd326271ee0863238a32f213a4704a7505442d4bbd06c7473e036c0dfb31c1f25584615189d801dc2515a25e4799
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/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 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
@@ -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
- around_template { template { yield_content(&block) } }
141
+ return buffer unless render?
147
142
 
148
- self.class.rendered_at_least_once ||= true
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
- 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
 
@@ -219,8 +224,9 @@ module Phlex
219
224
  end
220
225
 
221
226
  def unsafe_raw(content = nil, &block)
222
- @_target << (content || instance_exec(&block))
223
- nil
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
- private
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(v.transform_keys { "#{k}-#{_1.name.tr('_', '-')}" }, buffer: buffer)
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
@@ -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.1.0"
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.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: 2022-11-27 00:00:00.000000000 Z
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: 1.3.1
86
+ version: '0'
87
87
  requirements: []
88
88
  rubygems_version: 3.3.25
89
89
  signing_key: