rbexy 2.0.0.beta4 → 2.0.0.beta5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/lib/rbexy/cache_component.rb +17 -0
- data/lib/rbexy/component.rb +26 -15
- data/lib/rbexy/component_resolver.rb +8 -8
- data/lib/rbexy/configuration.rb +1 -1
- data/lib/rbexy/rails.rb +2 -0
- data/lib/rbexy/rails/component_template_resolver.rb +59 -4
- data/lib/rbexy/rails/engine.rb +2 -0
- data/lib/rbexy/rails/rbx_dependency_tracker.rb +37 -0
- data/lib/rbexy/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d36622639519d2abe9b9306612de65de836294ad529109d0ed5c1f8f11c0750
|
4
|
+
data.tar.gz: bae1042c6e80c5ec1a4f609162eee4d1efc66f340a6e742bc22d315bf486f597
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 749d66a40e869ee18c086d1d1c299936fb8c65ab742492a575a6d1afbc400a8c553df5cb337edf57b43aa200e856ec38b4c2bf6acee3d458a2dcfb86831f4cf7
|
7
|
+
data.tar.gz: 88a13df06a488a65ebf7e6aad95051ae23fad394f628e66e667c2ed1584a4e6c33909209e11ccdb210fbc6f41c089f1ce8cef3b80283e099998290c7608e924e
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -301,7 +301,7 @@ By default, we'll look for a template file in the same directory as the class an
|
|
301
301
|
<h1>{@title}</h1>
|
302
302
|
```
|
303
303
|
|
304
|
-
You can call this component from another `.rbx` template file (`<PageHeader title="Hello" />`)—either one rendered by another component class or a Rails view file like `app/views/products/index.rbx`. Or you can call it from ERB (or any other template language) like `PageHeaderComponent.new(self, title: "Hello").
|
304
|
+
You can call this component from another `.rbx` template file (`<PageHeader title="Hello" />`)—either one rendered by another component class or a Rails view file like `app/views/products/index.rbx`. Or you can call it from ERB (or any other template language) like `PageHeaderComponent.new(self, title: "Hello").render_in`.
|
305
305
|
|
306
306
|
Your components and their templates run in the same context as traditional Rails views, so you have access to all of the view helpers you're used to as well as any custom helpers you've defined in `app/helpers/`.
|
307
307
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Rbexy
|
2
|
+
class CacheComponent < Rbexy::Component
|
3
|
+
def setup(key:)
|
4
|
+
@key = key
|
5
|
+
end
|
6
|
+
|
7
|
+
def call
|
8
|
+
@current_template = view_context.instance_variable_get(:@current_template)
|
9
|
+
|
10
|
+
capture do
|
11
|
+
cache @key, virtual_path: @current_template.virtual_path do
|
12
|
+
@output_buffer << content
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/rbexy/component.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "action_view"
|
2
|
+
require "active_support/core_ext/class/attribute"
|
2
3
|
|
3
4
|
module Rbexy
|
4
5
|
class Component < ActionView::Base
|
@@ -10,12 +11,22 @@ module Rbexy
|
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
class_attribute :component_file_location
|
15
|
+
|
16
|
+
def self.inherited(klass)
|
17
|
+
klass.component_file_location = caller_locations(1, 10).reject { |l| l.label == "inherited" }[0].absolute_path
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.template_path
|
21
|
+
TemplatePath.new(component_name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.call_component?
|
25
|
+
method_defined?(:call)
|
15
26
|
end
|
16
27
|
|
17
|
-
def component_name
|
18
|
-
|
28
|
+
def self.component_name
|
29
|
+
name.underscore
|
19
30
|
end
|
20
31
|
|
21
32
|
def initialize(view_context, **props)
|
@@ -35,18 +46,9 @@ module Rbexy
|
|
35
46
|
# call super(view_context).
|
36
47
|
def setup(**props); end
|
37
48
|
|
38
|
-
def
|
49
|
+
def render_in(_context = view_context, &block)
|
39
50
|
@content_block = block_given? ? block : nil
|
40
|
-
call
|
41
|
-
end
|
42
|
-
|
43
|
-
def call
|
44
|
-
path = TemplatePath.new(component_name)
|
45
|
-
template = view_context.lookup_context.find(path)
|
46
|
-
template.render(self, {})
|
47
|
-
rescue ActionView::Template::Error => error
|
48
|
-
error.set_backtrace clean_template_backtrace(error.backtrace)
|
49
|
-
raise error
|
51
|
+
self.class.call_component? ? call : _render
|
50
52
|
end
|
51
53
|
|
52
54
|
def content
|
@@ -61,6 +63,15 @@ module Rbexy
|
|
61
63
|
|
62
64
|
attr_reader :view_context, :content_block
|
63
65
|
|
66
|
+
def _render
|
67
|
+
path = self.class.template_path
|
68
|
+
template = view_context.lookup_context.find(path)
|
69
|
+
template.render(self, {})
|
70
|
+
rescue ActionView::Template::Error => error
|
71
|
+
error.set_backtrace clean_template_backtrace(error.backtrace)
|
72
|
+
raise error
|
73
|
+
end
|
74
|
+
|
64
75
|
def method_missing(meth, *args, &block)
|
65
76
|
view_context.send(meth, *args, &block)
|
66
77
|
end
|
@@ -19,6 +19,13 @@ module Rbexy
|
|
19
19
|
tspan tt u ul unknown use var video view wbr xmp
|
20
20
|
).to_set
|
21
21
|
|
22
|
+
def self.try_constantize
|
23
|
+
yield
|
24
|
+
rescue NameError => e
|
25
|
+
raise e unless e.message =~ /wrong constant name/ || e.message =~ /uninitialized constant/
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
22
29
|
attr_reader :component_namespaces
|
23
30
|
|
24
31
|
def initialize
|
@@ -43,18 +50,11 @@ module Rbexy
|
|
43
50
|
private
|
44
51
|
|
45
52
|
def find(name)
|
46
|
-
|
47
|
-
rescue NameError => e
|
48
|
-
raise e unless e.message =~ /wrong constant name/ || e.message =~ /uninitialized constant/
|
49
|
-
nil
|
53
|
+
self.class.try_constantize { ActiveSupport::Inflector.constantize("#{name.gsub(".", "::")}Component") }
|
50
54
|
end
|
51
55
|
|
52
56
|
def matching_namespaces(template)
|
53
57
|
component_namespaces.select { |path, ns| template.identifier.start_with?(path) }.values.flatten.uniq
|
54
58
|
end
|
55
|
-
|
56
|
-
def find!(name)
|
57
|
-
ActiveSupport::Inflector.constantize("#{name.gsub(".", "::")}Component")
|
58
|
-
end
|
59
59
|
end
|
60
60
|
end
|
data/lib/rbexy/configuration.rb
CHANGED
@@ -22,7 +22,7 @@ module Rbexy
|
|
22
22
|
def component_rendering_templates
|
23
23
|
@component_rendering_templates ||= {
|
24
24
|
children: "{capture{%{children}}}",
|
25
|
-
component: "::%{component_class}.new(%{view_context},%{kwargs}).
|
25
|
+
component: "::%{component_class}.new(%{view_context},%{kwargs}).render_in%{children_block}"
|
26
26
|
}
|
27
27
|
end
|
28
28
|
end
|
data/lib/rbexy/rails.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
module Rbexy
|
2
2
|
autoload :Component, "rbexy/component"
|
3
|
+
autoload :CacheComponent, "rbexy/cache_component"
|
3
4
|
|
4
5
|
module Rails
|
5
6
|
autoload :Engine, "rbexy/rails/engine"
|
6
7
|
autoload :ControllerHelper, "rbexy/rails/controller_helper"
|
7
8
|
autoload :ComponentTemplateResolver, "rbexy/rails/component_template_resolver"
|
9
|
+
autoload :RbxDependencyTracker, "rbexy/rails/rbx_dependency_tracker"
|
8
10
|
end
|
9
11
|
end
|
@@ -1,7 +1,13 @@
|
|
1
|
+
require "active_support/digest"
|
2
|
+
|
1
3
|
module Rbexy
|
2
4
|
module Rails
|
3
5
|
class ComponentTemplateResolver < ActionView::FileSystemResolver
|
4
|
-
|
6
|
+
COMMENT_SYNTAX = {
|
7
|
+
rbx: "# %s",
|
8
|
+
erb: "<%# %s %>",
|
9
|
+
html: "<!-- %s -->"
|
10
|
+
}
|
5
11
|
|
6
12
|
# Rails 6 requires us to override `_find_all` in order to hook
|
7
13
|
def _find_all(name, prefix, partial, details, key, locals)
|
@@ -14,22 +20,71 @@ module Rbexy
|
|
14
20
|
return [] unless name.is_a? Rbexy::Component::TemplatePath
|
15
21
|
|
16
22
|
templates_path = File.join(@path, prefix, name)
|
23
|
+
component_name = prefix.present? ? File.join(prefix, name) : name
|
24
|
+
virtual_path = Rbexy::Component::TemplatePath.new(component_name)
|
25
|
+
|
17
26
|
extensions = details[:handlers].join(",")
|
27
|
+
templates = find_rbx_templates(templates_path, extensions, component_name, virtual_path)
|
28
|
+
|
29
|
+
if templates.none?
|
30
|
+
templates = find_call_component_cachebuster_templates(templates_path, component_name, virtual_path)
|
31
|
+
end
|
32
|
+
|
33
|
+
templates
|
34
|
+
end
|
18
35
|
|
36
|
+
def find_rbx_templates(templates_path, extensions, component_name, virtual_path)
|
19
37
|
Dir["#{templates_path}.*{#{extensions}}"].map do |template_path|
|
20
38
|
source = File.binread(template_path)
|
21
|
-
|
22
|
-
|
39
|
+
extension = File.extname(template_path)[1..-1]
|
40
|
+
handler = ActionView::Template.handler_for_extension(extension)
|
23
41
|
|
24
42
|
ActionView::Template.new(
|
25
|
-
source,
|
43
|
+
"#{source}#{component_class_cachebuster(component_name, extension)}",
|
26
44
|
template_path,
|
27
45
|
handler,
|
46
|
+
format: extension.to_sym,
|
28
47
|
locals: [],
|
29
48
|
virtual_path: virtual_path
|
30
49
|
)
|
31
50
|
end
|
32
51
|
end
|
52
|
+
|
53
|
+
def find_call_component_cachebuster_templates(templates_path, component_name, virtual_path)
|
54
|
+
component_class = find_component_class(component_name)
|
55
|
+
return [] unless component_class && component_class.call_component?
|
56
|
+
|
57
|
+
[
|
58
|
+
ActionView::Template.new(
|
59
|
+
cachebuster_digest_as_comment(component_class.component_file_location, :rbx),
|
60
|
+
"#{templates_path}.rbexycall",
|
61
|
+
ActionView::Template.handler_for_extension(:rbx),
|
62
|
+
format: :rbx,
|
63
|
+
locals: [],
|
64
|
+
virtual_path: virtual_path
|
65
|
+
)
|
66
|
+
]
|
67
|
+
end
|
68
|
+
|
69
|
+
def component_class_cachebuster(component_name, template_format)
|
70
|
+
component_class = find_component_class(component_name)
|
71
|
+
return unless component_class
|
72
|
+
|
73
|
+
cachebuster_digest_as_comment(component_class.component_file_location, template_format)
|
74
|
+
end
|
75
|
+
|
76
|
+
def find_component_class(component_name)
|
77
|
+
Rbexy::ComponentResolver.try_constantize { component_name.classify.constantize }
|
78
|
+
end
|
79
|
+
|
80
|
+
def cachebuster_digest_as_comment(filename, format)
|
81
|
+
source = File.binread(filename)
|
82
|
+
digest = ActiveSupport::Digest.hexdigest(source)
|
83
|
+
|
84
|
+
comment_template = COMMENT_SYNTAX[format.to_sym] || COMMENT_SYNTAX[:html]
|
85
|
+
comment = comment_template % digest
|
86
|
+
"\n#{comment}"
|
87
|
+
end
|
33
88
|
end
|
34
89
|
end
|
35
90
|
end
|
data/lib/rbexy/rails/engine.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "rbexy/rails"
|
2
|
+
require "action_view/dependency_tracker"
|
2
3
|
|
3
4
|
module Rbexy
|
4
5
|
module Rails
|
@@ -7,6 +8,7 @@ module Rbexy
|
|
7
8
|
template_handler = proc { |template, source| Rbexy.compile(Rbexy::Template.new(source, template.identifier)) }
|
8
9
|
|
9
10
|
ActionView::Template.register_template_handler(:rbx, template_handler)
|
11
|
+
ActionView::DependencyTracker.register_tracker(:rbx, RbxDependencyTracker)
|
10
12
|
|
11
13
|
ActiveSupport.on_load :action_controller_base do
|
12
14
|
include ControllerHelper
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Rbexy
|
2
|
+
module Rails
|
3
|
+
class RbxDependencyTracker
|
4
|
+
def self.supports_view_paths?
|
5
|
+
true
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.call(name, template, view_paths = nil)
|
9
|
+
new(name, template, view_paths).dependencies
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(name, template, view_paths = nil)
|
13
|
+
@name, @template, @view_paths = name, template, view_paths
|
14
|
+
end
|
15
|
+
|
16
|
+
def dependencies
|
17
|
+
rails_render_helper_dependencies + rbexy_dependencies
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :name, :template, :view_paths
|
23
|
+
|
24
|
+
def rails_render_helper_dependencies
|
25
|
+
ActionView::DependencyTracker::ERBTracker.call(name, template, view_paths)
|
26
|
+
end
|
27
|
+
|
28
|
+
def rbexy_dependencies
|
29
|
+
Lexer.new(template, Rbexy.configuration.element_resolver).tokenize
|
30
|
+
.select { |t| t[0] == :TAG_DETAILS && t[1][:type] == :component }
|
31
|
+
.map { |t| t[1][:component_class] }
|
32
|
+
.uniq
|
33
|
+
.map(&:template_path)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/rbexy/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbexy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.beta5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Giancola
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-01-
|
11
|
+
date: 2021-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -217,6 +217,7 @@ files:
|
|
217
217
|
- docker-compose.yml
|
218
218
|
- lib/rbexy.rb
|
219
219
|
- lib/rbexy/ast_transformer.rb
|
220
|
+
- lib/rbexy/cache_component.rb
|
220
221
|
- lib/rbexy/component.rb
|
221
222
|
- lib/rbexy/component/backtrace_cleaner.rb
|
222
223
|
- lib/rbexy/component_context.rb
|
@@ -244,6 +245,7 @@ files:
|
|
244
245
|
- lib/rbexy/rails/component_template_resolver.rb
|
245
246
|
- lib/rbexy/rails/controller_helper.rb
|
246
247
|
- lib/rbexy/rails/engine.rb
|
248
|
+
- lib/rbexy/rails/rbx_dependency_tracker.rb
|
247
249
|
- lib/rbexy/refinements.rb
|
248
250
|
- lib/rbexy/refinements/array.rb
|
249
251
|
- lib/rbexy/refinements/array/find_map.rb
|