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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d9cb20a821099f8fd51a0abb4b80ad3b2d8d936afcfe240a4b99ea29f4dea92a
4
- data.tar.gz: aab32903c9632f245857c917b0b99743e5e58ddb8356fce1274c5dd2e4791b37
3
+ metadata.gz: 5d36622639519d2abe9b9306612de65de836294ad529109d0ed5c1f8f11c0750
4
+ data.tar.gz: bae1042c6e80c5ec1a4f609162eee4d1efc66f340a6e742bc22d315bf486f597
5
5
  SHA512:
6
- metadata.gz: a849303b1f41e2e6295558b09f1a608a3b24bca8317bde650c579c6a0da2206c67f1ea9bb49e4b7bf15e66497960fff70703845544a57271c4947e4abe16d5ef
7
- data.tar.gz: 5f08d1838d39cf38d3f3d727e5c1ea098255e81e4a2ab4affd2b67a77a10d7f55dccdff52114f5ce9d544238d81d09a66f548ed74961298026f7887ad30339fd
6
+ metadata.gz: 749d66a40e869ee18c086d1d1c299936fb8c65ab742492a575a6d1afbc400a8c553df5cb337edf57b43aa200e856ec38b4c2bf6acee3d458a2dcfb86831f4cf7
7
+ data.tar.gz: 88a13df06a488a65ebf7e6aad95051ae23fad394f628e66e667c2ed1584a4e6c33909209e11ccdb210fbc6f41c089f1ce8cef3b80283e099998290c7608e924e
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rbexy (2.0.0.beta4)
4
+ rbexy (2.0.0.beta5)
5
5
  actionview (>= 6.0, < 7.0)
6
6
  activesupport (>= 6.0, < 7.0)
7
7
 
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").render`.
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
@@ -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
- def self.component_name
14
- name.underscore
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
- self.class.component_name
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 render(&block)
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
- find!(name)
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
@@ -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}).render%{children_block}"
25
+ component: "::%{component_class}.new(%{view_context},%{kwargs}).render_in%{children_block}"
26
26
  }
27
27
  end
28
28
  end
@@ -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
- VIRTUAL_ROOT = "rbexy_component".freeze
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
- handler = ActionView::Template.handler_for_extension(File.extname(template_path)[1..-1])
22
- virtual_path = File.join(VIRTUAL_ROOT, prefix, name)
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Rbexy
2
- VERSION = "2.0.0.beta4"
2
+ VERSION = "2.0.0.beta5"
3
3
  end
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.beta4
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-16 00:00:00.000000000 Z
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