phlex 2.0.0.rc2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -21
- data/lib/phlex/errors/runtime_error.rb +5 -0
- data/lib/phlex/fifo_cache_store.rb +3 -1
- data/lib/phlex/html/standard_elements.rb +517 -828
- data/lib/phlex/html/void_elements.rb +47 -80
- data/lib/phlex/html.rb +71 -9
- data/lib/phlex/kit.rb +11 -2
- data/lib/phlex/sgml/elements.rb +8 -8
- data/lib/phlex/sgml/state.rb +2 -3
- data/lib/phlex/sgml.rb +22 -16
- data/lib/phlex/svg.rb +39 -0
- data/lib/phlex/version.rb +1 -1
- data/lib/phlex.rb +45 -12
- metadata +7 -11
- data/lib/phlex/null_cache_store.rb +0 -9
- data/lib/phlex/testing/capybara.rb +0 -28
- data/lib/phlex/testing/nokogiri.rb +0 -19
- data/lib/phlex/testing/nokolexbor.rb +0 -19
- data/lib/phlex/testing/sgml.rb +0 -9
- data/lib/phlex/testing.rb +0 -10
@@ -5,95 +5,62 @@ module Phlex::HTML::VoidElements
|
|
5
5
|
extend Phlex::SGML::Elements
|
6
6
|
|
7
7
|
# Outputs an `<area>` tag.
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
**attributes
|
13
|
-
) = nil
|
8
|
+
# [MDN Docs](https://developer.mozilla.org/docs/Web/HTML/Element/area)
|
9
|
+
# [Spec](https://html.spec.whatwg.org/#the-area-element)
|
10
|
+
__register_void_element__ def area(**attributes) = nil
|
11
|
+
|
14
12
|
# Outputs a `<base>` tag.
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
id: nil,
|
20
|
-
target: nil,
|
21
|
-
**attributes
|
22
|
-
) = nil
|
13
|
+
# [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)
|
14
|
+
# [Spec](https://html.spec.whatwg.org/#the-base-element)
|
15
|
+
__register_void_element__ def base(**attributes) = nil
|
16
|
+
|
23
17
|
# Outputs a `<br>` tag.
|
24
|
-
#
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
**attributes
|
29
|
-
) = nil
|
18
|
+
# [MDN Docs](https://developer.mozilla.org/docs/Web/HTML/Element/br)
|
19
|
+
# [Spec](https://html.spec.whatwg.org/#the-br-element)
|
20
|
+
__register_void_element__ def br(**attributes) = nil
|
21
|
+
|
30
22
|
# Outputs a `<col>` tag.
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
**attributes
|
36
|
-
) = nil
|
23
|
+
# [MDN Docs](https://developer.mozilla.org/docs/Web/HTML/Element/col)
|
24
|
+
# [Spec](https://html.spec.whatwg.org/#the-col-element)
|
25
|
+
__register_void_element__ def col(**attributes) = nil
|
26
|
+
|
37
27
|
# Outputs an `<embed>` tag.
|
38
|
-
#
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
**attributes
|
43
|
-
) = nil
|
28
|
+
# [MDN Docs](https://developer.mozilla.org/docs/Web/HTML/Element/embed)
|
29
|
+
# [Spec](https://html.spec.whatwg.org/#the-embed-element)
|
30
|
+
__register_void_element__ def embed(**attributes) = nil
|
31
|
+
|
44
32
|
# Outputs an `<hr>` tag.
|
45
|
-
#
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
**attributes
|
50
|
-
) = nil
|
33
|
+
# [MDN Docs](https://developer.mozilla.org/docs/Web/HTML/Element/hr)
|
34
|
+
# [Spec](https://html.spec.whatwg.org/#the-hr-element)
|
35
|
+
__register_void_element__ def hr(**attributes) = nil
|
36
|
+
|
51
37
|
# Outputs an `<img>` tag.
|
52
|
-
#
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
id: nil,
|
57
|
-
src: nil,
|
58
|
-
**attributes
|
59
|
-
) = nil
|
38
|
+
# [MDN Docs](https://developer.mozilla.org/docs/Web/HTML/Element/img)
|
39
|
+
# [Spec](https://html.spec.whatwg.org/#the-img-element)
|
40
|
+
__register_void_element__ def img(**attributes) = nil
|
41
|
+
|
60
42
|
# Outputs an `<input>` tag.
|
61
|
-
#
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
name: nil,
|
66
|
-
type: nil,
|
67
|
-
**attributes
|
68
|
-
) = nil
|
43
|
+
# [MDN Docs](https://developer.mozilla.org/docs/Web/HTML/Element/input)
|
44
|
+
# [Spec](https://html.spec.whatwg.org/#the-input-element)
|
45
|
+
__register_void_element__ def input(**attributes) = nil
|
46
|
+
|
69
47
|
# Outputs a `<link>` tag.
|
70
|
-
#
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
**attributes
|
75
|
-
) = nil
|
48
|
+
# [MDN Docs](https://developer.mozilla.org/docs/Web/HTML/Element/link)
|
49
|
+
# [Spec](https://html.spec.whatwg.org/#the-link-element)
|
50
|
+
__register_void_element__ def link(**attributes) = nil
|
51
|
+
|
76
52
|
# Outputs a `<meta>` tag.
|
77
|
-
#
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
id: nil,
|
82
|
-
name: nil,
|
83
|
-
**attributes
|
84
|
-
) = nil
|
53
|
+
# [MDN Docs](https://developer.mozilla.org/docs/Web/HTML/Element/meta)
|
54
|
+
# [Spec](https://html.spec.whatwg.org/#the-meta-element)
|
55
|
+
__register_void_element__ def meta(**attributes) = nil
|
56
|
+
|
85
57
|
# Outputs a `<source>` tag.
|
86
|
-
#
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
**attributes
|
91
|
-
) = nil
|
58
|
+
# [MDN Docs](https://developer.mozilla.org/docs/Web/HTML/Element/source)
|
59
|
+
# [Spec](https://html.spec.whatwg.org/#the-source-element)
|
60
|
+
__register_void_element__ def source(**attributes) = nil
|
61
|
+
|
92
62
|
# Outputs a `<track>` tag.
|
93
|
-
#
|
94
|
-
|
95
|
-
|
96
|
-
id: nil,
|
97
|
-
**attributes
|
98
|
-
) = nil
|
63
|
+
# [MDN Docs](https://developer.mozilla.org/docs/Web/HTML/Element/track)
|
64
|
+
# [Spec](https://html.spec.whatwg.org/#the-track-element)
|
65
|
+
__register_void_element__ def track(**attributes) = nil
|
99
66
|
end
|
data/lib/phlex/html.rb
CHANGED
@@ -16,26 +16,88 @@ class Phlex::HTML < Phlex::SGML
|
|
16
16
|
nil
|
17
17
|
end
|
18
18
|
|
19
|
-
# Outputs an `<svg>` tag
|
20
|
-
#
|
21
|
-
#
|
22
|
-
|
19
|
+
# Outputs an `<svg>` tag.
|
20
|
+
#
|
21
|
+
# [MDN Docs](https://developer.mozilla.org/docs/Web/SVG/Element/svg)
|
22
|
+
# [Spec](https://html.spec.whatwg.org/#the-svg-element)
|
23
|
+
def svg(*, **, &)
|
23
24
|
if block_given?
|
24
|
-
super
|
25
|
-
render Phlex::SVG.new do |svg|
|
26
|
-
yield(svg)
|
27
|
-
end
|
28
|
-
end
|
25
|
+
super { render Phlex::SVG.new(&) }
|
29
26
|
else
|
30
27
|
super
|
31
28
|
end
|
32
29
|
end
|
33
30
|
|
31
|
+
# Override to provide a filename for the HTML file
|
34
32
|
def filename
|
35
33
|
nil
|
36
34
|
end
|
37
35
|
|
36
|
+
# Returns the string "text/html"
|
38
37
|
def content_type
|
39
38
|
"text/html"
|
40
39
|
end
|
40
|
+
|
41
|
+
# Output an HTML tag dynamically, e.g:
|
42
|
+
#
|
43
|
+
# ```ruby
|
44
|
+
# @tag_name = :h1
|
45
|
+
# tag(@tag_name, class: "title")
|
46
|
+
# ```
|
47
|
+
def tag(name, **attributes, &)
|
48
|
+
state = @_state
|
49
|
+
block_given = block_given?
|
50
|
+
buffer = state.buffer
|
51
|
+
|
52
|
+
unless state.should_render?
|
53
|
+
yield(self) if block_given
|
54
|
+
return nil
|
55
|
+
end
|
56
|
+
|
57
|
+
unless Symbol === name
|
58
|
+
raise Phlex::ArgumentError.new("Expected the tag name to be a Symbol.")
|
59
|
+
end
|
60
|
+
|
61
|
+
if (tag = StandardElements.__registered_elements__[name]) || (tag = name.name.tr("_", "-")).include?("-")
|
62
|
+
if attributes.length > 0 # with attributes
|
63
|
+
if block_given # with content block
|
64
|
+
buffer << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[attributes] ||= __attributes__(attributes)) << ">"
|
65
|
+
if tag == "svg"
|
66
|
+
render Phlex::SVG.new(&)
|
67
|
+
else
|
68
|
+
__yield_content__(&)
|
69
|
+
end
|
70
|
+
buffer << "</#{tag}>"
|
71
|
+
else # without content
|
72
|
+
buffer << "<#{tag}" << (::Phlex::ATTRIBUTE_CACHE[attributes] ||= __attributes__(attributes)) << "></#{tag}>"
|
73
|
+
end
|
74
|
+
else # without attributes
|
75
|
+
if block_given # with content block
|
76
|
+
buffer << ("<#{tag}>")
|
77
|
+
if tag == "svg"
|
78
|
+
render Phlex::SVG.new(&)
|
79
|
+
else
|
80
|
+
__yield_content__(&)
|
81
|
+
end
|
82
|
+
buffer << "</#{tag}>"
|
83
|
+
else # without content
|
84
|
+
buffer << "<#{tag}></#{tag}>"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
elsif (tag = VoidElements.__registered_elements__[name])
|
88
|
+
if block_given
|
89
|
+
raise Phlex::ArgumentError.new("Void elements cannot have content blocks.")
|
90
|
+
end
|
91
|
+
|
92
|
+
if attributes.length > 0 # with attributes
|
93
|
+
buffer << "<#{tag}" << (::Phlex::ATTRIBUTE_CACHE[attributes] ||= __attributes__(attributes)) << ">"
|
94
|
+
else # without attributes
|
95
|
+
buffer << "<#{tag}>"
|
96
|
+
end
|
97
|
+
|
98
|
+
nil
|
99
|
+
else
|
100
|
+
raise Phlex::ArgumentError.new("Invalid HTML tag: #{name}")
|
101
|
+
end
|
102
|
+
end
|
41
103
|
end
|
data/lib/phlex/kit.rb
CHANGED
@@ -24,7 +24,16 @@ module Phlex::Kit
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def self.extended(mod)
|
27
|
-
mod
|
27
|
+
case mod
|
28
|
+
when Class
|
29
|
+
raise Phlex::ArgumentError.new(<<~MESSAGE)
|
30
|
+
`Phlex::Kit` was extended into #{mod.name}.
|
31
|
+
|
32
|
+
You should only extend modules with `Phlex::Kit` as it is not compatible with classes.
|
33
|
+
MESSAGE
|
34
|
+
else
|
35
|
+
mod.include(LazyLoader)
|
36
|
+
end
|
28
37
|
end
|
29
38
|
|
30
39
|
def method_missing(name, ...)
|
@@ -52,7 +61,7 @@ module Phlex::Kit
|
|
52
61
|
case constant
|
53
62
|
when Class
|
54
63
|
if constant < Phlex::SGML
|
55
|
-
constant.include(
|
64
|
+
constant.include(me)
|
56
65
|
|
57
66
|
constant = nil
|
58
67
|
|
data/lib/phlex/sgml/elements.rb
CHANGED
@@ -27,14 +27,14 @@ module Phlex::SGML::Elements
|
|
27
27
|
content = yield(self)
|
28
28
|
if original_length == buffer.bytesize
|
29
29
|
case content
|
30
|
-
when
|
31
|
-
|
30
|
+
when ::Phlex::SGML::SafeObject
|
31
|
+
buffer << content.to_s
|
32
32
|
when String
|
33
33
|
buffer << ::Phlex::Escape.html_escape(content)
|
34
34
|
when Symbol
|
35
35
|
buffer << ::Phlex::Escape.html_escape(content.name)
|
36
|
-
when
|
37
|
-
|
36
|
+
when nil
|
37
|
+
nil
|
38
38
|
else
|
39
39
|
if (formatted_object = format_object(content))
|
40
40
|
buffer << ::Phlex::Escape.html_escape(formatted_object)
|
@@ -54,14 +54,14 @@ module Phlex::SGML::Elements
|
|
54
54
|
content = yield(self)
|
55
55
|
if original_length == buffer.bytesize
|
56
56
|
case content
|
57
|
-
when
|
58
|
-
|
57
|
+
when ::Phlex::SGML::SafeObject
|
58
|
+
buffer << content.to_s
|
59
59
|
when String
|
60
60
|
buffer << ::Phlex::Escape.html_escape(content)
|
61
61
|
when Symbol
|
62
62
|
buffer << ::Phlex::Escape.html_escape(content.name)
|
63
|
-
when
|
64
|
-
|
63
|
+
when nil
|
64
|
+
nil
|
65
65
|
else
|
66
66
|
if (formatted_object = format_object(content))
|
67
67
|
buffer << ::Phlex::Escape.html_escape(formatted_object)
|
data/lib/phlex/sgml/state.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Phlex::SGML::State
|
4
|
-
def initialize(user_context: {},
|
4
|
+
def initialize(user_context: {}, output_buffer:, fragments:)
|
5
5
|
@buffer = +""
|
6
6
|
@capturing = false
|
7
7
|
@user_context = user_context
|
@@ -9,13 +9,12 @@ class Phlex::SGML::State
|
|
9
9
|
@fragment_depth = 0
|
10
10
|
@cache_stack = []
|
11
11
|
@halt_signal = nil
|
12
|
-
@view_context = view_context
|
13
12
|
@output_buffer = output_buffer
|
14
13
|
end
|
15
14
|
|
16
15
|
attr_accessor :buffer, :capturing, :user_context
|
17
16
|
|
18
|
-
attr_reader :fragments, :fragment_depth, :
|
17
|
+
attr_reader :fragments, :fragment_depth, :output_buffer
|
19
18
|
|
20
19
|
def around_render(component)
|
21
20
|
stack = @stack
|
data/lib/phlex/sgml.rb
CHANGED
@@ -43,10 +43,9 @@ class Phlex::SGML
|
|
43
43
|
proc { |c| c.render(self) }
|
44
44
|
end
|
45
45
|
|
46
|
-
def call(buffer = +"", context: {},
|
46
|
+
def call(buffer = +"", context: {}, fragments: nil, &)
|
47
47
|
state = Phlex::SGML::State.new(
|
48
48
|
user_context: context,
|
49
|
-
view_context:,
|
50
49
|
output_buffer: buffer,
|
51
50
|
fragments: fragments&.to_set,
|
52
51
|
)
|
@@ -188,6 +187,7 @@ class Phlex::SGML
|
|
188
187
|
|
189
188
|
alias_method :🦺, :safe
|
190
189
|
|
190
|
+
# Flush the current state to the output buffer.
|
191
191
|
def flush
|
192
192
|
@_state.flush
|
193
193
|
end
|
@@ -195,9 +195,7 @@ class Phlex::SGML
|
|
195
195
|
def render(renderable = nil, &)
|
196
196
|
case renderable
|
197
197
|
when Phlex::SGML
|
198
|
-
Thread.current[:__phlex_component__] = [renderable, Fiber.current.object_id].freeze
|
199
198
|
renderable.internal_call(state: @_state, parent: self, &)
|
200
|
-
Thread.current[:__phlex_component__] = [self, Fiber.current.object_id].freeze
|
201
199
|
when Class
|
202
200
|
if renderable < Phlex::SGML
|
203
201
|
render(renderable.new, &)
|
@@ -206,7 +204,7 @@ class Phlex::SGML
|
|
206
204
|
renderable.each { |r| render(r, &) }
|
207
205
|
when Proc, Method
|
208
206
|
if renderable.arity == 0
|
209
|
-
|
207
|
+
__yield_content_with_no_yield_args__(&renderable)
|
210
208
|
else
|
211
209
|
__yield_content__(&renderable)
|
212
210
|
end
|
@@ -234,11 +232,12 @@ class Phlex::SGML
|
|
234
232
|
location = caller_locations(1, 1)[0]
|
235
233
|
|
236
234
|
full_key = [
|
237
|
-
|
238
|
-
self.class.name,
|
239
|
-
|
240
|
-
location.
|
241
|
-
|
235
|
+
app_version_key, # invalidates the key when deploying new code in case of changes
|
236
|
+
self.class.name, # prevents collisions between classes
|
237
|
+
(self.class.object_id if enable_cache_reloading?), # enables reloading
|
238
|
+
location.base_label, # prevents collisions between different methods
|
239
|
+
location.lineno, # prevents collisions between different lines
|
240
|
+
cache_key, # allows for custom cache keys
|
242
241
|
].freeze
|
243
242
|
|
244
243
|
low_level_cache(full_key, **, &content)
|
@@ -277,14 +276,21 @@ class Phlex::SGML
|
|
277
276
|
end
|
278
277
|
end
|
279
278
|
|
280
|
-
|
281
|
-
|
279
|
+
private
|
280
|
+
|
281
|
+
# Override this method to use a different deployment key.
|
282
|
+
def app_version_key
|
283
|
+
Phlex::DEPLOYED_AT
|
284
|
+
end
|
285
|
+
|
282
286
|
# Override this method to use a different cache store.
|
283
287
|
def cache_store
|
284
|
-
|
288
|
+
raise "Cache store not implemented."
|
285
289
|
end
|
286
290
|
|
287
|
-
|
291
|
+
def enable_cache_reloading?
|
292
|
+
false
|
293
|
+
end
|
288
294
|
|
289
295
|
def vanish(*args)
|
290
296
|
return unless block_given?
|
@@ -334,13 +340,13 @@ class Phlex::SGML
|
|
334
340
|
nil
|
335
341
|
end
|
336
342
|
|
337
|
-
def
|
343
|
+
def __yield_content_with_no_yield_args__
|
338
344
|
return unless block_given?
|
339
345
|
|
340
346
|
buffer = @_state.buffer
|
341
347
|
|
342
348
|
original_length = buffer.bytesize
|
343
|
-
content = yield
|
349
|
+
content = yield # <-- doesn’t yield self 😉
|
344
350
|
__implicit_output__(content) if original_length == buffer.bytesize
|
345
351
|
|
346
352
|
nil
|
data/lib/phlex/svg.rb
CHANGED
@@ -5,11 +5,50 @@ class Phlex::SVG < Phlex::SGML
|
|
5
5
|
|
6
6
|
include StandardElements
|
7
7
|
|
8
|
+
# Returns the string "image/svg+xml"
|
8
9
|
def content_type
|
9
10
|
"image/svg+xml"
|
10
11
|
end
|
11
12
|
|
13
|
+
# Override to provide a filename for the SVG file
|
12
14
|
def filename
|
13
15
|
nil
|
14
16
|
end
|
17
|
+
|
18
|
+
def tag(name, **attributes, &)
|
19
|
+
state = @_state
|
20
|
+
block_given = block_given?
|
21
|
+
buffer = state.buffer
|
22
|
+
|
23
|
+
unless state.should_render?
|
24
|
+
yield(self) if block_given
|
25
|
+
return nil
|
26
|
+
end
|
27
|
+
|
28
|
+
unless Symbol === name
|
29
|
+
raise Phlex::ArgumentError.new("Expected the tag name to be a Symbol.")
|
30
|
+
end
|
31
|
+
|
32
|
+
if (tag = StandardElements.__registered_elements__[name]) || (tag = name.name.tr("_", "-")).include?("-")
|
33
|
+
if attributes.length > 0 # with attributes
|
34
|
+
if block_given # with content block
|
35
|
+
buffer << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[attributes] ||= __attributes__(attributes)) << ">"
|
36
|
+
__yield_content__(&)
|
37
|
+
buffer << "</#{tag}>"
|
38
|
+
else # without content
|
39
|
+
buffer << "<#{tag}" << (::Phlex::ATTRIBUTE_CACHE[attributes] ||= __attributes__(attributes)) << "></#{tag}>"
|
40
|
+
end
|
41
|
+
else # without attributes
|
42
|
+
if block_given # with content block
|
43
|
+
buffer << ("<#{tag}>")
|
44
|
+
__yield_content__(&)
|
45
|
+
buffer << "</#{tag}>"
|
46
|
+
else # without content
|
47
|
+
buffer << "<#{tag}></#{tag}>"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
else
|
51
|
+
raise Phlex::ArgumentError.new("Invalid SVG tag: #{name}")
|
52
|
+
end
|
53
|
+
end
|
15
54
|
end
|
data/lib/phlex/version.rb
CHANGED
data/lib/phlex.rb
CHANGED
@@ -4,25 +4,26 @@ require "erb"
|
|
4
4
|
require "set"
|
5
5
|
|
6
6
|
module Phlex
|
7
|
-
autoload :
|
8
|
-
autoload :CSV, "phlex/csv"
|
9
|
-
autoload :DoubleRenderError, "phlex/errors/double_render_error"
|
10
|
-
autoload :Error, "phlex/error"
|
7
|
+
autoload :Kit, "phlex/kit"
|
11
8
|
autoload :FIFO, "phlex/fifo"
|
9
|
+
autoload :Vanish, "phlex/vanish"
|
10
|
+
autoload :Helpers, "phlex/helpers"
|
12
11
|
autoload :FIFOCacheStore, "phlex/fifo_cache_store"
|
12
|
+
|
13
|
+
autoload :CSV, "phlex/csv"
|
14
|
+
autoload :SVG, "phlex/svg"
|
13
15
|
autoload :HTML, "phlex/html"
|
14
|
-
autoload :Helpers, "phlex/helpers"
|
15
|
-
autoload :Kit, "phlex/kit"
|
16
|
-
autoload :NameError, "phlex/errors/name_error"
|
17
|
-
autoload :NullCacheStore, "phlex/null_cache_store"
|
18
16
|
autoload :SGML, "phlex/sgml"
|
19
|
-
|
20
|
-
autoload :
|
17
|
+
|
18
|
+
autoload :Error, "phlex/error"
|
19
|
+
autoload :NameError, "phlex/errors/name_error"
|
20
|
+
autoload :RuntimeError, "phlex/errors/runtime_error"
|
21
|
+
autoload :ArgumentError, "phlex/errors/argument_error"
|
22
|
+
autoload :DoubleRenderError, "phlex/errors/double_render_error"
|
21
23
|
|
22
24
|
Escape = ERB::Escape
|
23
|
-
Null = Object.new.freeze
|
24
25
|
|
25
|
-
|
26
|
+
DEPLOYED_AT = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
26
27
|
CACHED_FILES = Set.new
|
27
28
|
ATTRIBUTE_CACHE = FIFO.new
|
28
29
|
|
@@ -43,6 +44,38 @@ module Phlex
|
|
43
44
|
end
|
44
45
|
end
|
45
46
|
end
|
47
|
+
|
48
|
+
# Generate an HTML string using Phlex’ HTML DSL
|
49
|
+
def self.html(&block)
|
50
|
+
HTML.call do |component|
|
51
|
+
receiver = block.binding.receiver
|
52
|
+
|
53
|
+
receiver.instance_variables.each do |ivar|
|
54
|
+
next if component.instance_variable_defined?(ivar)
|
55
|
+
|
56
|
+
value = receiver.instance_variable_get(ivar)
|
57
|
+
component.instance_variable_set(ivar, value)
|
58
|
+
end
|
59
|
+
|
60
|
+
component.instance_exec(receiver, &block)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Generate an SVG string using Phlex’ SVG DSL
|
65
|
+
def self.svg(&block)
|
66
|
+
SVG.call do |component|
|
67
|
+
receiver = block.binding.receiver
|
68
|
+
|
69
|
+
receiver.instance_variables.each do |ivar|
|
70
|
+
next if component.instance_variable_defined?(ivar)
|
71
|
+
|
72
|
+
value = receiver.instance_variable_get(ivar)
|
73
|
+
component.instance_variable_set(ivar, value)
|
74
|
+
end
|
75
|
+
|
76
|
+
component.instance_exec(receiver, &block)
|
77
|
+
end
|
78
|
+
end
|
46
79
|
end
|
47
80
|
|
48
81
|
def 💪
|
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: phlex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Drapper
|
8
|
+
- Will Cosgrove
|
8
9
|
bindir: bin
|
9
10
|
cert_chain: []
|
10
|
-
date: 2025-02-
|
11
|
+
date: 2025-02-14 00:00:00.000000000 Z
|
11
12
|
dependencies: []
|
12
|
-
description:
|
13
|
+
description: Build HTML & SVG view components with Ruby classes.
|
13
14
|
email:
|
14
15
|
- joel@drapper.me
|
15
16
|
executables: []
|
@@ -24,6 +25,7 @@ files:
|
|
24
25
|
- lib/phlex/errors/argument_error.rb
|
25
26
|
- lib/phlex/errors/double_render_error.rb
|
26
27
|
- lib/phlex/errors/name_error.rb
|
28
|
+
- lib/phlex/errors/runtime_error.rb
|
27
29
|
- lib/phlex/fifo.rb
|
28
30
|
- lib/phlex/fifo_cache_store.rb
|
29
31
|
- lib/phlex/helpers.rb
|
@@ -31,7 +33,6 @@ files:
|
|
31
33
|
- lib/phlex/html/standard_elements.rb
|
32
34
|
- lib/phlex/html/void_elements.rb
|
33
35
|
- lib/phlex/kit.rb
|
34
|
-
- lib/phlex/null_cache_store.rb
|
35
36
|
- lib/phlex/sgml.rb
|
36
37
|
- lib/phlex/sgml/elements.rb
|
37
38
|
- lib/phlex/sgml/safe_object.rb
|
@@ -39,11 +40,6 @@ files:
|
|
39
40
|
- lib/phlex/sgml/state.rb
|
40
41
|
- lib/phlex/svg.rb
|
41
42
|
- lib/phlex/svg/standard_elements.rb
|
42
|
-
- lib/phlex/testing.rb
|
43
|
-
- lib/phlex/testing/capybara.rb
|
44
|
-
- lib/phlex/testing/nokogiri.rb
|
45
|
-
- lib/phlex/testing/nokolexbor.rb
|
46
|
-
- lib/phlex/testing/sgml.rb
|
47
43
|
- lib/phlex/vanish.rb
|
48
44
|
- lib/phlex/version.rb
|
49
45
|
homepage: https://www.phlex.fun
|
@@ -52,7 +48,7 @@ licenses:
|
|
52
48
|
metadata:
|
53
49
|
homepage_uri: https://www.phlex.fun
|
54
50
|
source_code_uri: https://github.com/phlex-ruby/phlex
|
55
|
-
changelog_uri: https://github.com/phlex-ruby/phlex/
|
51
|
+
changelog_uri: https://github.com/phlex-ruby/phlex/releases
|
56
52
|
funding_uri: https://github.com/sponsors/joeldrapper
|
57
53
|
rubygems_mfa_required: 'true'
|
58
54
|
rdoc_options: []
|
@@ -71,5 +67,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
67
|
requirements: []
|
72
68
|
rubygems_version: 3.6.2
|
73
69
|
specification_version: 4
|
74
|
-
summary:
|
70
|
+
summary: Object-oriented views in Ruby.
|
75
71
|
test_files: []
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "capybara"
|
4
|
-
|
5
|
-
module Phlex::Testing::Capybara
|
6
|
-
include Phlex::Testing::SGML
|
7
|
-
|
8
|
-
def self.included(mod)
|
9
|
-
if defined?(Minitest::Test) && Minitest::Test > mod
|
10
|
-
require "capybara/minitest"
|
11
|
-
mod.include Capybara::Minitest::Assertions
|
12
|
-
end
|
13
|
-
|
14
|
-
if defined?(RSpec::Core::ExampleGroup) && RSpec::Core::ExampleGroup > mod
|
15
|
-
require "capybara/rspec"
|
16
|
-
mod.include Capybara::RSpecMatchers
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
attr_reader :page
|
21
|
-
alias_method :component, :page
|
22
|
-
|
23
|
-
def render(...)
|
24
|
-
@page = ::Capybara::Node::Simple.new(
|
25
|
-
render_to_string(...),
|
26
|
-
)
|
27
|
-
end
|
28
|
-
end
|