phlex 1.5.3 → 1.6.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/.ruby-version +1 -1
- data/lib/phlex/context.rb +22 -0
- data/lib/phlex/elements.rb +8 -8
- data/lib/phlex/html.rb +1 -1
- data/lib/phlex/sgml.rb +38 -46
- data/lib/phlex/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eeac8033b47d1e0cf99832bc7a42a7777ca44643dd503f3cb08087666b08d4f7
|
4
|
+
data.tar.gz: 6f7e786e982dcc9133c40179d4bb582d9d45bb610814020e916a2afbf17cb0d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 037caf900c1155b1e9095588a30dff67a7f224b6e16365d417dc7412e34822cb1368a194a4e48de65c20a838b91f671e7e53fca7a0f0e973852d84ebc7c03d3c
|
7
|
+
data.tar.gz: 85ad16185650ff8aa04831c745ac6709ae35913863af0fef5a70d671d75dbbdf389005db6480cb5c4533ad9e3106379cb6aa2015b64194ca78a2dd8b61cd3993
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.2.1
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Phlex::Context
|
4
|
+
def initialize
|
5
|
+
@target = +""
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_accessor :target
|
9
|
+
|
10
|
+
def with_target(new_target)
|
11
|
+
original_target = @target
|
12
|
+
|
13
|
+
begin
|
14
|
+
@target = new_target
|
15
|
+
yield
|
16
|
+
ensure
|
17
|
+
@target = original_target
|
18
|
+
end
|
19
|
+
|
20
|
+
new_target
|
21
|
+
end
|
22
|
+
end
|
data/lib/phlex/elements.rb
CHANGED
@@ -20,19 +20,19 @@ module Phlex::Elements
|
|
20
20
|
def __phlex_#{element}__(**attributes, &block)
|
21
21
|
if attributes.length > 0 # with attributes
|
22
22
|
if block_given? # with content block
|
23
|
-
@
|
23
|
+
@_context.target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[respond_to?(:process_attributes) ? (attributes.hash + self.class.hash) : attributes.hash] || __attributes__(**attributes)) << ">"
|
24
24
|
yield_content(&block)
|
25
|
-
@
|
25
|
+
@_context.target << "</#{tag}>"
|
26
26
|
else # without content block
|
27
|
-
@
|
27
|
+
@_context.target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[respond_to?(:process_attributes) ? (attributes.hash + self.class.hash) : attributes.hash] || __attributes__(**attributes)) << "></#{tag}>"
|
28
28
|
end
|
29
29
|
else # without attributes
|
30
30
|
if block_given? # with content block
|
31
|
-
@
|
31
|
+
@_context.target << "<#{tag}>"
|
32
32
|
yield_content(&block)
|
33
|
-
@
|
33
|
+
@_context.target << "</#{tag}>"
|
34
34
|
else # without content block
|
35
|
-
@
|
35
|
+
@_context.target << "<#{tag}></#{tag}>"
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
@@ -53,9 +53,9 @@ module Phlex::Elements
|
|
53
53
|
|
54
54
|
def __phlex_#{element}__(**attributes)
|
55
55
|
if attributes.length > 0 # with attributes
|
56
|
-
@
|
56
|
+
@_context.target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[respond_to?(:process_attributes) ? (attributes.hash + self.class.hash) : attributes.hash] || __attributes__(**attributes)) << ">"
|
57
57
|
else # without attributes
|
58
|
-
@
|
58
|
+
@_context.target << "<#{tag}>"
|
59
59
|
end
|
60
60
|
|
61
61
|
nil
|
data/lib/phlex/html.rb
CHANGED
data/lib/phlex/sgml.rb
CHANGED
@@ -34,21 +34,21 @@ module Phlex
|
|
34
34
|
end
|
35
35
|
|
36
36
|
# Renders the view and returns the buffer. The default buffer is a mutable String.
|
37
|
-
def call(buffer = nil,
|
38
|
-
__final_call__(buffer,
|
37
|
+
def call(buffer = nil, context: Phlex::Context.new, view_context: nil, parent: nil, &block)
|
38
|
+
__final_call__(buffer, context: context, view_context: view_context, parent: parent, &block).tap do
|
39
39
|
self.class.rendered_at_least_once!
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
43
|
# @api private
|
44
|
-
def __final_call__(buffer = nil,
|
45
|
-
@
|
44
|
+
def __final_call__(buffer = nil, context: Phlex::Context.new, view_context: nil, parent: nil, &block)
|
45
|
+
@_context = context
|
46
46
|
@_view_context = view_context
|
47
47
|
@_parent = parent
|
48
48
|
|
49
49
|
block ||= @_content_block
|
50
50
|
|
51
|
-
return buffer || target unless render?
|
51
|
+
return buffer || context.target unless render?
|
52
52
|
|
53
53
|
around_template do
|
54
54
|
if block
|
@@ -69,7 +69,7 @@ module Phlex
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
buffer ? (buffer << target) : target
|
72
|
+
buffer ? (buffer << context.target) : context.target
|
73
73
|
end
|
74
74
|
|
75
75
|
# Render another view
|
@@ -78,11 +78,15 @@ module Phlex
|
|
78
78
|
def render(renderable, &block)
|
79
79
|
case renderable
|
80
80
|
when Phlex::SGML
|
81
|
-
renderable.call(
|
81
|
+
renderable.call(context: @_context, view_context: @_view_context, parent: self, &block)
|
82
82
|
when Class
|
83
83
|
if renderable < Phlex::SGML
|
84
|
-
renderable.new.call(
|
84
|
+
renderable.new.call(context: @_context, view_context: @_view_context, parent: self, &block)
|
85
85
|
end
|
86
|
+
when Enumerable
|
87
|
+
renderable.each { |r| render(r, &block) }
|
88
|
+
when Proc
|
89
|
+
yield_content(&renderable)
|
86
90
|
else
|
87
91
|
raise ArgumentError, "You can't render a #{renderable}."
|
88
92
|
end
|
@@ -95,16 +99,16 @@ module Phlex
|
|
95
99
|
def plain(content)
|
96
100
|
case content
|
97
101
|
when String
|
98
|
-
@
|
102
|
+
@_context.target << ERB::Escape.html_escape(content)
|
99
103
|
when Symbol
|
100
|
-
@
|
104
|
+
@_context.target << ERB::Escape.html_escape(content.name)
|
101
105
|
when Integer
|
102
|
-
@
|
106
|
+
@_context.target << ERB::Escape.html_escape(content.to_s)
|
103
107
|
when nil
|
104
108
|
nil
|
105
109
|
else
|
106
110
|
if (formatted_object = format_object(content))
|
107
|
-
@
|
111
|
+
@_context.target << ERB::Escape.html_escape(formatted_object)
|
108
112
|
end
|
109
113
|
end
|
110
114
|
|
@@ -114,11 +118,11 @@ module Phlex
|
|
114
118
|
# Output a whitespace character. This is useful for getting inline elements to wrap. If you pass a block, a whitespace will be output before and after yielding the block.
|
115
119
|
# @return [nil]
|
116
120
|
def whitespace
|
117
|
-
@
|
121
|
+
@_context.target << " "
|
118
122
|
|
119
123
|
if block_given?
|
120
124
|
yield
|
121
|
-
@
|
125
|
+
@_context.target << " "
|
122
126
|
end
|
123
127
|
|
124
128
|
nil
|
@@ -127,9 +131,9 @@ module Phlex
|
|
127
131
|
# Output an HTML comment.
|
128
132
|
# @return [nil]
|
129
133
|
def comment(&block)
|
130
|
-
@
|
134
|
+
@_context.target << "<!-- "
|
131
135
|
yield_content(&block)
|
132
|
-
@
|
136
|
+
@_context.target << " -->"
|
133
137
|
|
134
138
|
nil
|
135
139
|
end
|
@@ -140,27 +144,17 @@ module Phlex
|
|
140
144
|
def unsafe_raw(content = nil)
|
141
145
|
return nil unless content
|
142
146
|
|
143
|
-
@
|
147
|
+
@_context.target << content
|
144
148
|
nil
|
145
149
|
end
|
146
150
|
|
147
151
|
# Capture a block of output as a String.
|
152
|
+
# @note This only works if the block's receiver is the current component or the block returns a String.
|
148
153
|
# @return [String]
|
149
154
|
def capture(&block)
|
150
|
-
return "" unless
|
155
|
+
return "" unless block
|
151
156
|
|
152
|
-
|
153
|
-
@_target.clear
|
154
|
-
|
155
|
-
begin
|
156
|
-
yield_content(&block)
|
157
|
-
new_buffer_content = @_target.dup
|
158
|
-
ensure
|
159
|
-
@_target.clear
|
160
|
-
@_target << original_buffer_content
|
161
|
-
end
|
162
|
-
|
163
|
-
new_buffer_content.is_a?(String) ? new_buffer_content : ""
|
157
|
+
@_context.with_target(+"") { yield_content(&block) }
|
164
158
|
end
|
165
159
|
|
166
160
|
# Like `capture` but the output is vanished into a BlackHole buffer.
|
@@ -169,14 +163,7 @@ module Phlex
|
|
169
163
|
private def __vanish__(*args)
|
170
164
|
return unless block_given?
|
171
165
|
|
172
|
-
|
173
|
-
|
174
|
-
begin
|
175
|
-
@_target = BlackHole
|
176
|
-
yield(*args)
|
177
|
-
ensure
|
178
|
-
@_target = original_buffer
|
179
|
-
end
|
166
|
+
@_context.with_target(BlackHole) { yield(*args) }
|
180
167
|
|
181
168
|
nil
|
182
169
|
end
|
@@ -223,10 +210,10 @@ module Phlex
|
|
223
210
|
private def yield_content
|
224
211
|
return unless block_given?
|
225
212
|
|
226
|
-
original_length = @
|
213
|
+
original_length = @_context.target.length
|
227
214
|
content = yield(self)
|
228
215
|
|
229
|
-
plain(content) if original_length == @
|
216
|
+
plain(content) if original_length == @_context.target.length
|
230
217
|
|
231
218
|
nil
|
232
219
|
end
|
@@ -236,9 +223,9 @@ module Phlex
|
|
236
223
|
private def yield_content_with_args(*args)
|
237
224
|
return unless block_given?
|
238
225
|
|
239
|
-
original_length = @
|
226
|
+
original_length = @_context.target.length
|
240
227
|
content = yield(*args)
|
241
|
-
plain(content) if original_length == @
|
228
|
+
plain(content) if original_length == @_context.target.length
|
242
229
|
|
243
230
|
nil
|
244
231
|
end
|
@@ -256,6 +243,14 @@ module Phlex
|
|
256
243
|
attributes = process_attributes(**attributes)
|
257
244
|
end
|
258
245
|
|
246
|
+
if attributes[:href]&.start_with?(/\s*javascript:/)
|
247
|
+
attributes.delete(:href)
|
248
|
+
end
|
249
|
+
|
250
|
+
if attributes["href"]&.start_with?(/\s*javascript:/)
|
251
|
+
attributes.delete("href")
|
252
|
+
end
|
253
|
+
|
259
254
|
buffer = +""
|
260
255
|
__build_attributes__(attributes, buffer: buffer)
|
261
256
|
|
@@ -273,11 +268,8 @@ module Phlex
|
|
273
268
|
else k.to_s
|
274
269
|
end
|
275
270
|
|
276
|
-
lower_name = name.downcase
|
277
|
-
next if lower_name == "href" && v.to_s.downcase.tr("\t \n", "").start_with?("javascript:")
|
278
|
-
|
279
271
|
# Detect unsafe attribute names. Attribute names are considered unsafe if they match an event attribute or include unsafe characters.
|
280
|
-
if HTML::EVENT_ATTRIBUTES[
|
272
|
+
if HTML::EVENT_ATTRIBUTES[name] || name.match?(/[<>&"']/)
|
281
273
|
raise ArgumentError, "Unsafe attribute name detected: #{k}."
|
282
274
|
end
|
283
275
|
|
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.6.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-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -76,6 +76,7 @@ files:
|
|
76
76
|
- lib/phlex.rb
|
77
77
|
- lib/phlex/black_hole.rb
|
78
78
|
- lib/phlex/callable.rb
|
79
|
+
- lib/phlex/context.rb
|
79
80
|
- lib/phlex/deferred_render.rb
|
80
81
|
- lib/phlex/element_clobbering_guard.rb
|
81
82
|
- lib/phlex/elements.rb
|
@@ -116,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
117
|
- !ruby/object:Gem::Version
|
117
118
|
version: '0'
|
118
119
|
requirements: []
|
119
|
-
rubygems_version: 3.
|
120
|
+
rubygems_version: 3.4.6
|
120
121
|
signing_key:
|
121
122
|
specification_version: 4
|
122
123
|
summary: A framework for building views in Ruby.
|