phlex 1.2.1 β 1.3.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/README.md +3 -3
- data/lib/phlex/deferred_render.rb +1 -1
- data/lib/phlex/html.rb +20 -11
- data/lib/phlex/unbuffered.rb +15 -14
- data/lib/phlex/version.rb +1 -1
- data/lib/phlex.rb +2 -11
- metadata +16 -6
- data/lib/phlex/collection.rb +0 -33
- data/lib/phlex/configuration.rb +0 -13
- data/lib/phlex/experimental.rb +0 -13
- data/lib/phlex/table.rb +0 -103
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8df07c966d273976d91feebba2528a5cdacb5bb28116af48a54f42a97128ad94
|
4
|
+
data.tar.gz: 638529d514e4d1938ec0c0bab224969cc16a252752da3e1ab67ae2f217f4ea3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3728d8501c975eef2caa6c8b7c78d98d0f4aa654a88787e13e58c608331112b06074a177f401f6691713e8bbc4eac863e2b318e6d58cc61a3bfa38319e69e82d
|
7
|
+
data.tar.gz: bfd075ce712b522da689ed643b9a52536a80a7e779b807e8994c00a623a9e45b8a051f2dc78166efeebed047f02cda97c10f70c8165b99325e9c0236937ab918
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<a href="https://www.phlex.fun"><img alt="Phlex logo" src="phlex_logo.png" width="180" /></a>
|
2
2
|
|
3
|
-
Phlex
|
3
|
+
Phlex lets you compose web views in pure Ruby. Itβs super-fast, thread-safe and supports TruffleRuby v22.2+, JRuby v9.2+ and MRI v2.7+.
|
4
4
|
|
5
5
|
### Documentation π
|
6
6
|
|
@@ -12,13 +12,13 @@ If you run into any trouble, please [start a discussion](https://github.com/joel
|
|
12
12
|
|
13
13
|
### Community π
|
14
14
|
|
15
|
-
Everyone interacting in Phlex codebases, issue trackers
|
15
|
+
Everyone interacting in Phlex codebases, issue trackers or chat rooms is expected to follow the [code of conduct](https://github.com/joeldrapper/phlex/blob/main/CODE_OF_CONDUCT.md).
|
16
16
|
|
17
17
|
### Who uses Phlex?
|
18
18
|
|
19
19
|
- [Clearscope](https://www.clearscope.io)
|
20
20
|
|
21
|
-
*If you
|
21
|
+
*If youβre using Phlex in production, please open a PR to list it here.*
|
22
22
|
|
23
23
|
### Sponsorship π
|
24
24
|
|
data/lib/phlex/html.rb
CHANGED
@@ -130,8 +130,6 @@ module Phlex
|
|
130
130
|
include Helpers
|
131
131
|
|
132
132
|
class << self
|
133
|
-
attr_accessor :rendered_at_least_once
|
134
|
-
|
135
133
|
def call(...)
|
136
134
|
new(...).call
|
137
135
|
end
|
@@ -146,9 +144,20 @@ module Phlex
|
|
146
144
|
super
|
147
145
|
end
|
148
146
|
end
|
147
|
+
|
148
|
+
def rendered_at_least_once!
|
149
|
+
alias_method :__attributes__, :__final_attributes__
|
150
|
+
alias_method :call, :__final_call__
|
151
|
+
end
|
149
152
|
end
|
150
153
|
|
151
|
-
def call(
|
154
|
+
def call(...)
|
155
|
+
__final_call__(...).tap do
|
156
|
+
self.class.rendered_at_least_once!
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def __final_call__(buffer = +"", view_context: nil, parent: nil, &block)
|
152
161
|
@_target = buffer
|
153
162
|
@_view_context = view_context
|
154
163
|
@_parent = parent
|
@@ -176,8 +185,6 @@ module Phlex
|
|
176
185
|
end
|
177
186
|
end
|
178
187
|
|
179
|
-
self.class.rendered_at_least_once = true
|
180
|
-
|
181
188
|
buffer
|
182
189
|
end
|
183
190
|
|
@@ -356,21 +363,23 @@ module Phlex
|
|
356
363
|
end
|
357
364
|
|
358
365
|
private def __attributes__(**attributes)
|
359
|
-
|
366
|
+
__final_attributes__(**attributes).tap do |buffer|
|
367
|
+
Phlex::ATTRIBUTE_CACHE[attributes.hash] = buffer.freeze
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
private def __final_attributes__(**attributes)
|
372
|
+
if attributes[:href]&.start_with?(/\s*javascript:/)
|
360
373
|
attributes.delete(:href)
|
361
374
|
end
|
362
375
|
|
363
|
-
if attributes["href"]&.start_with?(/\s*javascript
|
376
|
+
if attributes["href"]&.start_with?(/\s*javascript:/)
|
364
377
|
attributes.delete("href")
|
365
378
|
end
|
366
379
|
|
367
380
|
buffer = +""
|
368
381
|
__build_attributes__(attributes, buffer: buffer)
|
369
382
|
|
370
|
-
unless self.class.rendered_at_least_once
|
371
|
-
Phlex::ATTRIBUTE_CACHE[attributes.hash] = buffer.freeze
|
372
|
-
end
|
373
|
-
|
374
383
|
buffer
|
375
384
|
end
|
376
385
|
|
data/lib/phlex/unbuffered.rb
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
module Phlex
|
4
4
|
class Unbuffered < BasicObject
|
5
|
-
CACHE =
|
5
|
+
CACHE = ::Concurrent::Map.new
|
6
6
|
|
7
7
|
def self.call(object)
|
8
|
-
decorator = CACHE
|
8
|
+
decorator = CACHE.compute_if_absent(object.class.name) { ::Class.new(self) }
|
9
9
|
decorator.new(object)
|
10
10
|
end
|
11
11
|
|
@@ -31,10 +31,12 @@ module Phlex
|
|
31
31
|
@object.respond_to?(...)
|
32
32
|
end
|
33
33
|
|
34
|
-
def method_missing(name, *args, &block)
|
34
|
+
def method_missing(name, *args, **kwargs, &block)
|
35
35
|
if @object.respond_to?(name)
|
36
|
-
|
37
|
-
__class__.
|
36
|
+
|
37
|
+
__class__.define_method(name) do |*a, **k, &b|
|
38
|
+
@object.capture { @object.public_send(name, *a, **k, &b) }
|
39
|
+
end
|
38
40
|
|
39
41
|
# Now we've defined this missing method, we can call it.
|
40
42
|
__public_send__(name, *args, &block)
|
@@ -43,18 +45,17 @@ module Phlex
|
|
43
45
|
end
|
44
46
|
end
|
45
47
|
|
46
|
-
#
|
47
|
-
def
|
48
|
-
@object.
|
48
|
+
# Forward some methods to the original underlying method
|
49
|
+
def call(...)
|
50
|
+
@object.call(...)
|
49
51
|
end
|
50
52
|
|
51
|
-
def
|
52
|
-
@object.
|
53
|
+
def send(...)
|
54
|
+
@object.send(...)
|
53
55
|
end
|
54
56
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
alias_method :public_send, :__forward_method__
|
57
|
+
def public_send(...)
|
58
|
+
@object.public_send(...)
|
59
|
+
end
|
59
60
|
end
|
60
61
|
end
|
data/lib/phlex/version.rb
CHANGED
data/lib/phlex.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "erb"
|
4
4
|
require "zeitwerk"
|
5
|
+
require "concurrent"
|
5
6
|
|
6
7
|
module Phlex
|
7
8
|
Loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false).tap do |loader|
|
@@ -14,15 +15,5 @@ module Phlex
|
|
14
15
|
ArgumentError = Class.new(ArgumentError) { include Error }
|
15
16
|
NameError = Class.new(NameError) { include Error }
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
ATTRIBUTE_CACHE = {}
|
20
|
-
|
21
|
-
def configuration
|
22
|
-
@configuration ||= Configuration.new
|
23
|
-
end
|
24
|
-
|
25
|
-
def configure
|
26
|
-
yield configuration
|
27
|
-
end
|
18
|
+
ATTRIBUTE_CACHE = Concurrent::Map.new
|
28
19
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: phlex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.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: 2023-01-
|
11
|
+
date: 2023-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: concurrent-ruby
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.2'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: zeitwerk
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,14 +64,10 @@ files:
|
|
50
64
|
- lib/phlex/black_hole.rb
|
51
65
|
- lib/phlex/buffered.rb
|
52
66
|
- lib/phlex/callable.rb
|
53
|
-
- lib/phlex/collection.rb
|
54
|
-
- lib/phlex/configuration.rb
|
55
67
|
- lib/phlex/deferred_render.rb
|
56
68
|
- lib/phlex/elements.rb
|
57
|
-
- lib/phlex/experimental.rb
|
58
69
|
- lib/phlex/helpers.rb
|
59
70
|
- lib/phlex/html.rb
|
60
|
-
- lib/phlex/table.rb
|
61
71
|
- lib/phlex/testing/view_helper.rb
|
62
72
|
- lib/phlex/unbuffered.rb
|
63
73
|
- lib/phlex/version.rb
|
data/lib/phlex/collection.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Phlex
|
4
|
-
module Collection
|
5
|
-
include Experimental
|
6
|
-
|
7
|
-
def initialize(collection: nil, item: nil)
|
8
|
-
unless collection || item
|
9
|
-
raise ArgumentError, "You must pass a collection or an item as a keyword argument."
|
10
|
-
end
|
11
|
-
|
12
|
-
@collection = collection
|
13
|
-
@item = item
|
14
|
-
end
|
15
|
-
|
16
|
-
def template
|
17
|
-
@item ? item_template : collection_template { yield_items }
|
18
|
-
end
|
19
|
-
|
20
|
-
private def yield_items
|
21
|
-
if @item
|
22
|
-
raise ArgumentError, "You can only yield_items when rendering a collection. You are currently rendering an item."
|
23
|
-
end
|
24
|
-
|
25
|
-
@collection.each do |item|
|
26
|
-
@item = item
|
27
|
-
item_template
|
28
|
-
end
|
29
|
-
|
30
|
-
@item = nil
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
data/lib/phlex/configuration.rb
DELETED
data/lib/phlex/experimental.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Phlex
|
4
|
-
module Experimental
|
5
|
-
def before_template
|
6
|
-
if Phlex.configuration.experimental_warnings
|
7
|
-
puts "Warning: #{self.class.name} is using experimental Phlex features that are subject to change."
|
8
|
-
end
|
9
|
-
|
10
|
-
super
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
data/lib/phlex/table.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Phlex
|
4
|
-
module Table
|
5
|
-
include Experimental
|
6
|
-
include Collection
|
7
|
-
|
8
|
-
module ClassMethods
|
9
|
-
attr_accessor :header
|
10
|
-
|
11
|
-
def property(header = nil, **attributes, &body)
|
12
|
-
if header.is_a?(String)
|
13
|
-
header_text = header
|
14
|
-
header = -> { head_header(scope: "col") { header_text } }
|
15
|
-
end
|
16
|
-
|
17
|
-
properties << {
|
18
|
-
header: header,
|
19
|
-
body: body,
|
20
|
-
attributes: attributes,
|
21
|
-
}
|
22
|
-
end
|
23
|
-
|
24
|
-
def properties
|
25
|
-
@properties ||= []
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.included(child)
|
30
|
-
child.extend ClassMethods
|
31
|
-
|
32
|
-
child.alias_method :head, :thead
|
33
|
-
child.alias_method :body, :tbody
|
34
|
-
child.alias_method :foot, :tfoot
|
35
|
-
|
36
|
-
child.alias_method :row, :tr
|
37
|
-
|
38
|
-
child.alias_method :header, :th
|
39
|
-
child.alias_method :cell, :td
|
40
|
-
|
41
|
-
child.alias_method :head_row, :row
|
42
|
-
child.alias_method :body_row, :row
|
43
|
-
child.alias_method :foot_row, :row
|
44
|
-
|
45
|
-
child.alias_method :head_header, :header
|
46
|
-
child.alias_method :foot_header, :header
|
47
|
-
|
48
|
-
child.alias_method :head_cell, :cell
|
49
|
-
child.alias_method :body_cell, :cell
|
50
|
-
child.alias_method :foot_cell, :cell
|
51
|
-
end
|
52
|
-
|
53
|
-
private def properties
|
54
|
-
self.class.properties
|
55
|
-
end
|
56
|
-
|
57
|
-
private def collection_template(&block)
|
58
|
-
table do
|
59
|
-
head_template
|
60
|
-
body_template(&block)
|
61
|
-
foot_template
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
private def item_template
|
66
|
-
row_template
|
67
|
-
end
|
68
|
-
|
69
|
-
private def head_template
|
70
|
-
if self.class.properties.any? { |p| p[:header] }
|
71
|
-
head do
|
72
|
-
head_row do
|
73
|
-
self.class.properties.each do |property|
|
74
|
-
case property[:header]
|
75
|
-
when Proc
|
76
|
-
instance_exec(&property[:header])
|
77
|
-
when Symbol
|
78
|
-
send(property[:header])
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
private def body_template
|
87
|
-
body { yield_items }
|
88
|
-
end
|
89
|
-
|
90
|
-
private def foot_template
|
91
|
-
end
|
92
|
-
|
93
|
-
private def row_template
|
94
|
-
body_row do
|
95
|
-
self.class.properties.each do |property|
|
96
|
-
body_cell(**property[:attributes]) do
|
97
|
-
instance_exec(@item, &property[:body])
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|