phlex 2.0.0.beta2 → 2.0.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +8 -11
- data/lib/phlex/csv.rb +4 -11
- data/lib/phlex/error.rb +1 -0
- data/lib/phlex/fifo.rb +11 -3
- data/lib/phlex/fifo_cache_store.rb +49 -0
- data/lib/phlex/helpers.rb +2 -2
- data/lib/phlex/html/standard_elements.rb +932 -722
- data/lib/phlex/html/void_elements.rb +93 -66
- data/lib/phlex/html.rb +4 -10
- data/lib/phlex/kit.rb +39 -22
- data/lib/phlex/null_cache_store.rb +9 -0
- data/lib/phlex/sgml/elements.rb +112 -0
- data/lib/phlex/sgml/state.rb +118 -0
- data/lib/phlex/sgml.rb +326 -305
- data/lib/phlex/svg/standard_elements.rb +417 -449
- data/lib/phlex/svg.rb +0 -3
- data/lib/phlex/{black_hole.rb → vanish.rb} +1 -1
- data/lib/phlex/version.rb +1 -1
- data/lib/phlex.rb +17 -9
- metadata +9 -12
- data/lib/phlex/context.rb +0 -59
- data/lib/phlex/deferred_render.rb +0 -29
- data/lib/phlex/element_clobbering_guard.rb +0 -18
- data/lib/phlex/elements.rb +0 -172
data/lib/phlex/svg.rb
CHANGED
data/lib/phlex/version.rb
CHANGED
data/lib/phlex.rb
CHANGED
@@ -5,29 +5,26 @@ require "set"
|
|
5
5
|
|
6
6
|
module Phlex
|
7
7
|
autoload :ArgumentError, "phlex/errors/argument_error"
|
8
|
-
autoload :DoubleRenderError, "phlex/errors/double_render_error"
|
9
|
-
autoload :BlackHole, "phlex/black_hole"
|
10
8
|
autoload :CSV, "phlex/csv"
|
11
|
-
autoload :
|
12
|
-
autoload :Context, "phlex/context"
|
13
|
-
autoload :DeferredRender, "phlex/deferred_render"
|
14
|
-
autoload :ElementClobberingGuard, "phlex/element_clobbering_guard"
|
15
|
-
autoload :Elements, "phlex/elements"
|
9
|
+
autoload :DoubleRenderError, "phlex/errors/double_render_error"
|
16
10
|
autoload :Error, "phlex/error"
|
17
11
|
autoload :FIFO, "phlex/fifo"
|
12
|
+
autoload :FIFOCacheStore, "phlex/fifo_cache_store"
|
18
13
|
autoload :HTML, "phlex/html"
|
19
14
|
autoload :Helpers, "phlex/helpers"
|
20
15
|
autoload :Kit, "phlex/kit"
|
21
16
|
autoload :NameError, "phlex/errors/name_error"
|
17
|
+
autoload :NullCacheStore, "phlex/null_cache_store"
|
22
18
|
autoload :SGML, "phlex/sgml"
|
23
19
|
autoload :SVG, "phlex/svg"
|
20
|
+
autoload :Vanish, "phlex/vanish"
|
24
21
|
|
25
22
|
Escape = ERB::Escape
|
26
|
-
ATTRIBUTE_CACHE = FIFO.new
|
27
|
-
SUPPORTS_FIBER_STORAGE = RUBY_ENGINE == "ruby"
|
28
23
|
Null = Object.new.freeze
|
29
24
|
|
25
|
+
DEPLOY_KEY = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
30
26
|
CACHED_FILES = Set.new
|
27
|
+
ATTRIBUTE_CACHE = FIFO.new
|
31
28
|
|
32
29
|
def self.__expand_attribute_cache__(file_path)
|
33
30
|
unless CACHED_FILES.include?(file_path)
|
@@ -35,6 +32,17 @@ module Phlex
|
|
35
32
|
Phlex::ATTRIBUTE_CACHE.expand(File.size(file_path))
|
36
33
|
end
|
37
34
|
end
|
35
|
+
|
36
|
+
def self.eager_load
|
37
|
+
queue = [self]
|
38
|
+
|
39
|
+
while (mod = queue.shift)
|
40
|
+
mod.constants.each do |const_name|
|
41
|
+
const = mod.const_get(const_name)
|
42
|
+
queue << const if Module === const
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
38
46
|
end
|
39
47
|
|
40
48
|
def 💪
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
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.rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Drapper
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-02-10 00:00:00.000000000 Z
|
12
11
|
dependencies: []
|
13
12
|
description: A high-performance view framework optimised for fun.
|
14
13
|
email:
|
@@ -20,25 +19,24 @@ files:
|
|
20
19
|
- LICENSE.txt
|
21
20
|
- README.md
|
22
21
|
- lib/phlex.rb
|
23
|
-
- lib/phlex/black_hole.rb
|
24
|
-
- lib/phlex/context.rb
|
25
22
|
- lib/phlex/csv.rb
|
26
|
-
- lib/phlex/deferred_render.rb
|
27
|
-
- lib/phlex/element_clobbering_guard.rb
|
28
|
-
- lib/phlex/elements.rb
|
29
23
|
- lib/phlex/error.rb
|
30
24
|
- lib/phlex/errors/argument_error.rb
|
31
25
|
- lib/phlex/errors/double_render_error.rb
|
32
26
|
- lib/phlex/errors/name_error.rb
|
33
27
|
- lib/phlex/fifo.rb
|
28
|
+
- lib/phlex/fifo_cache_store.rb
|
34
29
|
- lib/phlex/helpers.rb
|
35
30
|
- lib/phlex/html.rb
|
36
31
|
- lib/phlex/html/standard_elements.rb
|
37
32
|
- lib/phlex/html/void_elements.rb
|
38
33
|
- lib/phlex/kit.rb
|
34
|
+
- lib/phlex/null_cache_store.rb
|
39
35
|
- lib/phlex/sgml.rb
|
36
|
+
- lib/phlex/sgml/elements.rb
|
40
37
|
- lib/phlex/sgml/safe_object.rb
|
41
38
|
- lib/phlex/sgml/safe_value.rb
|
39
|
+
- lib/phlex/sgml/state.rb
|
42
40
|
- lib/phlex/svg.rb
|
43
41
|
- lib/phlex/svg/standard_elements.rb
|
44
42
|
- lib/phlex/testing.rb
|
@@ -46,6 +44,7 @@ files:
|
|
46
44
|
- lib/phlex/testing/nokogiri.rb
|
47
45
|
- lib/phlex/testing/nokolexbor.rb
|
48
46
|
- lib/phlex/testing/sgml.rb
|
47
|
+
- lib/phlex/vanish.rb
|
49
48
|
- lib/phlex/version.rb
|
50
49
|
homepage: https://www.phlex.fun
|
51
50
|
licenses:
|
@@ -56,7 +55,6 @@ metadata:
|
|
56
55
|
changelog_uri: https://github.com/phlex-ruby/phlex/blob/main/CHANGELOG.md
|
57
56
|
funding_uri: https://github.com/sponsors/joeldrapper
|
58
57
|
rubygems_mfa_required: 'true'
|
59
|
-
post_install_message:
|
60
58
|
rdoc_options: []
|
61
59
|
require_paths:
|
62
60
|
- lib
|
@@ -64,15 +62,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
64
62
|
requirements:
|
65
63
|
- - ">="
|
66
64
|
- !ruby/object:Gem::Version
|
67
|
-
version: 3.
|
65
|
+
version: '3.2'
|
68
66
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
67
|
requirements:
|
70
68
|
- - ">="
|
71
69
|
- !ruby/object:Gem::Version
|
72
70
|
version: '0'
|
73
71
|
requirements: []
|
74
|
-
rubygems_version: 3.
|
75
|
-
signing_key:
|
72
|
+
rubygems_version: 3.6.2
|
76
73
|
specification_version: 4
|
77
74
|
summary: A fun framework for building views in Ruby.
|
78
75
|
test_files: []
|
data/lib/phlex/context.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# @api private
|
4
|
-
class Phlex::Context
|
5
|
-
def initialize(user_context = {})
|
6
|
-
@buffer = +""
|
7
|
-
@capturing = false
|
8
|
-
@user_context = user_context
|
9
|
-
@fragments = nil
|
10
|
-
@in_target_fragment = false
|
11
|
-
@halt_signal = nil
|
12
|
-
end
|
13
|
-
|
14
|
-
attr_accessor :buffer, :capturing, :user_context, :in_target_fragment
|
15
|
-
|
16
|
-
attr_reader :fragments
|
17
|
-
|
18
|
-
def target_fragments(fragments)
|
19
|
-
@fragments = fragments.to_h { |it| [it, true] }
|
20
|
-
end
|
21
|
-
|
22
|
-
def around_render
|
23
|
-
return yield if !@fragments || @halt_signal
|
24
|
-
|
25
|
-
catch do |signal|
|
26
|
-
@halt_signal = signal
|
27
|
-
yield
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def begin_target(id)
|
32
|
-
@in_target_fragment = id
|
33
|
-
end
|
34
|
-
|
35
|
-
def end_target
|
36
|
-
@fragments.delete(@in_target_fragment)
|
37
|
-
@in_target_fragment = false
|
38
|
-
throw @halt_signal if @fragments.length == 0
|
39
|
-
end
|
40
|
-
|
41
|
-
def capturing_into(new_buffer)
|
42
|
-
original_buffer = @buffer
|
43
|
-
original_capturing = @capturing
|
44
|
-
original_fragments = @fragments
|
45
|
-
|
46
|
-
begin
|
47
|
-
@buffer = new_buffer
|
48
|
-
@capturing = true
|
49
|
-
@fragments = nil
|
50
|
-
yield
|
51
|
-
ensure
|
52
|
-
@buffer = original_buffer
|
53
|
-
@capturing = original_capturing
|
54
|
-
@fragments = original_fragments
|
55
|
-
end
|
56
|
-
|
57
|
-
new_buffer
|
58
|
-
end
|
59
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Include this module into an {HTML} or {SVG} component to make it yield the content block before calling {#template}.
|
4
|
-
# @example
|
5
|
-
# class Tabs < Phlex::HTML
|
6
|
-
# include DeferredRender
|
7
|
-
#
|
8
|
-
# Tab = Data.define(:name, :content)
|
9
|
-
#
|
10
|
-
# def initialize
|
11
|
-
# @tabs = []
|
12
|
-
# end
|
13
|
-
#
|
14
|
-
# def view_template
|
15
|
-
# @tabs.each { |t| a { t.name } }
|
16
|
-
# @tabs.each { |t| article(&t.content) }
|
17
|
-
# end
|
18
|
-
#
|
19
|
-
# def tab(name, &content)
|
20
|
-
# @tabs << Tab.new(name, content)
|
21
|
-
# end
|
22
|
-
# end
|
23
|
-
module Phlex::DeferredRender
|
24
|
-
# This module doesn't do anything. Phlex::HTML#call checks for its inclusion in the ancestry instead.
|
25
|
-
|
26
|
-
# @!method template
|
27
|
-
# @abstract Override to define your own template.
|
28
|
-
# @note {DeferredRender} templates do not receive the content block. Instead, it is yielded in advance.
|
29
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# @api private
|
4
|
-
module Phlex::ElementClobberingGuard
|
5
|
-
def method_added(method_name)
|
6
|
-
if method_name[0] == "_" && __element_method__?(method_name[1..].to_sym)
|
7
|
-
raise Phlex::NameError.new("👋 Redefining the method `#{name}##{method_name}` is not a good idea.")
|
8
|
-
elsif method_name == :view_template
|
9
|
-
location = instance_method(method_name).source_location[0]
|
10
|
-
|
11
|
-
if location[0] in "/" | "."
|
12
|
-
Phlex.__expand_attribute_cache__(location)
|
13
|
-
end
|
14
|
-
else
|
15
|
-
super
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/lib/phlex/elements.rb
DELETED
@@ -1,172 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Extending this module provides the {register_element} macro for registering your own custom elements. It's already extended by {HTML} and {SVG}.
|
4
|
-
# @example
|
5
|
-
# module MyCustomElements
|
6
|
-
# extend Phlex::Elements
|
7
|
-
#
|
8
|
-
# register_element :trix_editor
|
9
|
-
# end
|
10
|
-
#
|
11
|
-
# class MyComponent < Phlex::HTML
|
12
|
-
# include MyCustomElements
|
13
|
-
#
|
14
|
-
# def view_template
|
15
|
-
# trix_editor
|
16
|
-
# end
|
17
|
-
# end
|
18
|
-
module Phlex::Elements
|
19
|
-
# @api private
|
20
|
-
def registered_elements
|
21
|
-
@registered_elements ||= {}
|
22
|
-
end
|
23
|
-
|
24
|
-
# Register a custom element. This macro defines an element method for the current class and descendents only. There is no global element registry.
|
25
|
-
# @param method_name [Symbol]
|
26
|
-
# @param tag [String] the name of the tag, otherwise this will be the method name with underscores replaced with dashes.
|
27
|
-
# @return [Symbol] the name of the method created
|
28
|
-
# @note The methods defined by this macro depend on other methods from {SGML} so they should always be mixed into an {HTML} or {SVG} component.
|
29
|
-
# @example Register the custom element `<trix-editor>`
|
30
|
-
# register_element :trix_editor
|
31
|
-
def register_element(method_name, tag: method_name.name.tr("_", "-"))
|
32
|
-
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
33
|
-
# frozen_string_literal: true
|
34
|
-
|
35
|
-
def #{method_name}(**attributes)
|
36
|
-
context = @_context
|
37
|
-
buffer = context.buffer
|
38
|
-
fragment = context.fragments
|
39
|
-
target_found = false
|
40
|
-
block_given = block_given?
|
41
|
-
|
42
|
-
if fragment
|
43
|
-
return if fragment.length == 0 # we found all our fragments already
|
44
|
-
|
45
|
-
id = attributes[:id]
|
46
|
-
|
47
|
-
if !context.in_target_fragment
|
48
|
-
if fragment[id]
|
49
|
-
context.begin_target(id)
|
50
|
-
target_found = true
|
51
|
-
else
|
52
|
-
yield(self) if block_given
|
53
|
-
return nil
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
if attributes.length > 0 # with attributes
|
59
|
-
if block_given # with content block
|
60
|
-
buffer << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[attributes] ||= __attributes__(attributes)) << ">"
|
61
|
-
|
62
|
-
original_length = buffer.bytesize
|
63
|
-
content = yield(self)
|
64
|
-
if original_length == buffer.bytesize
|
65
|
-
case content
|
66
|
-
when String
|
67
|
-
buffer << ::Phlex::Escape.html_escape(content)
|
68
|
-
when Symbol
|
69
|
-
buffer << ::Phlex::Escape.html_escape(content.name)
|
70
|
-
when nil
|
71
|
-
nil
|
72
|
-
when ::Phlex::SGML::SafeObject
|
73
|
-
buffer << content.to_s
|
74
|
-
else
|
75
|
-
if (formatted_object = format_object(content))
|
76
|
-
buffer << ::Phlex::Escape.html_escape(formatted_object)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
buffer << "</#{tag}>"
|
82
|
-
else # without content
|
83
|
-
buffer << "<#{tag}" << (::Phlex::ATTRIBUTE_CACHE[attributes] ||= __attributes__(attributes)) << "></#{tag}>"
|
84
|
-
end
|
85
|
-
else # without attributes
|
86
|
-
if block_given # with content block
|
87
|
-
buffer << "<#{tag}>"
|
88
|
-
|
89
|
-
original_length = buffer.bytesize
|
90
|
-
content = yield(self)
|
91
|
-
if original_length == buffer.bytesize
|
92
|
-
case content
|
93
|
-
when String
|
94
|
-
buffer << ::Phlex::Escape.html_escape(content)
|
95
|
-
when Symbol
|
96
|
-
buffer << ::Phlex::Escape.html_escape(content.name)
|
97
|
-
when nil
|
98
|
-
nil
|
99
|
-
when ::Phlex::SGML::SafeObject
|
100
|
-
buffer << content.to_s
|
101
|
-
else
|
102
|
-
if (formatted_object = format_object(content))
|
103
|
-
buffer << ::Phlex::Escape.html_escape(formatted_object)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
buffer << "</#{tag}>"
|
109
|
-
else # without content
|
110
|
-
buffer << "<#{tag}></#{tag}>"
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
#{'flush' if tag == 'head'}
|
115
|
-
|
116
|
-
context.end_target if target_found
|
117
|
-
|
118
|
-
nil
|
119
|
-
end
|
120
|
-
|
121
|
-
alias_method :_#{method_name}, :#{method_name}
|
122
|
-
RUBY
|
123
|
-
|
124
|
-
registered_elements[method_name] = tag
|
125
|
-
|
126
|
-
method_name
|
127
|
-
end
|
128
|
-
|
129
|
-
# @api private
|
130
|
-
def register_void_element(method_name, tag: method_name.name.tr("_", "-"))
|
131
|
-
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
132
|
-
# frozen_string_literal: true
|
133
|
-
|
134
|
-
def #{method_name}(**attributes)
|
135
|
-
context = @_context
|
136
|
-
buffer = context.buffer
|
137
|
-
fragment = context.fragments
|
138
|
-
|
139
|
-
if fragment
|
140
|
-
return if fragment.length == 0 # we found all our fragments already
|
141
|
-
|
142
|
-
id = attributes[:id]
|
143
|
-
|
144
|
-
if !context.in_target_fragment
|
145
|
-
if fragment[id]
|
146
|
-
context.begin_target(id)
|
147
|
-
target_found = true
|
148
|
-
else
|
149
|
-
return nil
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
if attributes.length > 0 # with attributes
|
155
|
-
buffer << "<#{tag}" << (::Phlex::ATTRIBUTE_CACHE[attributes] ||= __attributes__(attributes)) << ">"
|
156
|
-
else # without attributes
|
157
|
-
buffer << "<#{tag}>"
|
158
|
-
end
|
159
|
-
|
160
|
-
context.end_target if target_found
|
161
|
-
|
162
|
-
nil
|
163
|
-
end
|
164
|
-
|
165
|
-
alias_method :_#{method_name}, :#{method_name}
|
166
|
-
RUBY
|
167
|
-
|
168
|
-
registered_elements[method_name] = tag
|
169
|
-
|
170
|
-
method_name
|
171
|
-
end
|
172
|
-
end
|