rbexy 0.2.2 → 1.0.1
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/.gitignore +3 -2
- data/Gemfile.lock +2 -2
- data/README.md +2 -0
- data/docker-compose.yml +12 -0
- data/lib/rbexy.rb +0 -1
- data/lib/rbexy/component.rb +28 -51
- data/lib/rbexy/component/backtrace_cleaner.rb +59 -0
- data/lib/rbexy/configuration.rb +2 -0
- data/lib/rbexy/lexer.rb +1 -2
- data/lib/rbexy/nodes.rb +16 -19
- data/lib/rbexy/rails.rb +2 -0
- data/lib/rbexy/rails/component_template_resolver.rb +35 -0
- data/lib/rbexy/rails/controller_helper.rb +20 -0
- data/lib/rbexy/rails/engine.rb +2 -2
- data/lib/rbexy/runtime.rb +1 -0
- data/lib/rbexy/version.rb +1 -1
- data/lib/rbexy/view_context_helper.rb +12 -0
- data/rbexy.gemspec +1 -1
- metadata +7 -5
- data/lib/rbexy/output_buffer.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 203d3f0d86ddbf38e11477ca082fec2bd1e4bc1e2843b4a74e08ea593f35a276
|
4
|
+
data.tar.gz: b41f015a023954be101bc01339eeee51f13893fc39918906a4e9d62b4bbfca6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d038e97f116998e004329938a371d510c7c96d034ab16a1bab0755971397d9020eb7c0459e2bf4f5e95acf9d9a6008b0d9cab208a36f9cab6d2fb7db8e953652
|
7
|
+
data.tar.gz: 503b6f70c7e2c7cfaa76e5dc77382cba4c6ecead1b7837d1870a025a71cf638a09bb1f96a5c74a7b8ac8aa7ef9cbcc030d1d109214fb8406d65eb46211c6fb3b
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rbexy (0.
|
4
|
+
rbexy (1.0.1)
|
5
5
|
actionview (>= 5.0, < 7.0)
|
6
6
|
activesupport (>= 5.0, < 7.0)
|
7
7
|
railties (>= 5.0, < 7.0)
|
@@ -201,7 +201,7 @@ PLATFORMS
|
|
201
201
|
DEPENDENCIES
|
202
202
|
guard-rspec (~> 4.7, >= 4.7.3)
|
203
203
|
pry-byebug
|
204
|
-
rails (>=
|
204
|
+
rails (>= 6.0, < 7.0)
|
205
205
|
rake
|
206
206
|
rbexy!
|
207
207
|
rspec (~> 3.9)
|
data/README.md
CHANGED
data/docker-compose.yml
CHANGED
@@ -6,6 +6,7 @@ volumes:
|
|
6
6
|
services:
|
7
7
|
rbexy:
|
8
8
|
build: .
|
9
|
+
image: rbexy
|
9
10
|
volumes:
|
10
11
|
- .:/app
|
11
12
|
- bundle:/usr/local/bundle
|
@@ -13,3 +14,14 @@ services:
|
|
13
14
|
- $HOME/.gitconfig:/root/.gitconfig:ro
|
14
15
|
- $HOME/.gem/credentials:/root/.gem/credentials
|
15
16
|
working_dir: /app
|
17
|
+
dummy:
|
18
|
+
image: rbexy
|
19
|
+
volumes:
|
20
|
+
- .:/app
|
21
|
+
- bundle:/usr/local/bundle
|
22
|
+
working_dir: /app/spec/dummy/
|
23
|
+
command: ./start.sh
|
24
|
+
ports:
|
25
|
+
- 3000:3000
|
26
|
+
environment:
|
27
|
+
- RAILS_LOG_STDOUT=1
|
data/lib/rbexy.rb
CHANGED
@@ -6,7 +6,6 @@ module Rbexy
|
|
6
6
|
autoload :Nodes, "rbexy/nodes"
|
7
7
|
autoload :Runtime, "rbexy/runtime"
|
8
8
|
autoload :HashMash, "rbexy/hash_mash"
|
9
|
-
autoload :OutputBuffer, "rbexy/output_buffer"
|
10
9
|
autoload :ComponentTagBuilder, "rbexy/component_tag_builder"
|
11
10
|
autoload :ViewContextHelper, "rbexy/view_context_helper"
|
12
11
|
autoload :Configuration, "rbexy/configuration"
|
data/lib/rbexy/component.rb
CHANGED
@@ -1,27 +1,24 @@
|
|
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
|
5
|
-
|
6
|
-
attr_accessor :component_name_stack
|
7
|
-
|
8
|
-
def self.details_hash(context)
|
9
|
-
context.registered_details.each_with_object({}) do |key, details_hash|
|
10
|
-
value = key == :locale ? [context.locale] : context.send(key)
|
11
|
-
details_hash[key] = value
|
12
|
-
end
|
13
|
-
end
|
6
|
+
autoload :BacktraceCleaner, "rbexy/component/backtrace_cleaner"
|
14
7
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
# functionality but don't want our templates prefixed with a `_`
|
19
|
-
def args_for_lookup(name, prefixes, partial, keys, details_options)
|
20
|
-
partial = false if component_name_stack.include?(name)
|
21
|
-
super(name, prefixes, partial, keys, details_options)
|
8
|
+
class TemplatePath < String
|
9
|
+
def to_s
|
10
|
+
self
|
22
11
|
end
|
23
12
|
end
|
24
13
|
|
14
|
+
def self.component_name
|
15
|
+
name.underscore
|
16
|
+
end
|
17
|
+
|
18
|
+
def component_name
|
19
|
+
self.class.component_name
|
20
|
+
end
|
21
|
+
|
25
22
|
def initialize(view_context, **props)
|
26
23
|
super(
|
27
24
|
view_context.lookup_context,
|
@@ -45,14 +42,16 @@ module Rbexy
|
|
45
42
|
end
|
46
43
|
|
47
44
|
def call
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
45
|
+
path = TemplatePath.new(component_name)
|
46
|
+
template = view_context.lookup_context.find(path)
|
47
|
+
template.render(self, {})
|
48
|
+
rescue ActionView::Template::Error => error
|
49
|
+
error.set_backtrace clean_template_backtrace(error.backtrace)
|
50
|
+
raise error
|
52
51
|
end
|
53
52
|
|
54
53
|
def content
|
55
|
-
content_block ?
|
54
|
+
content_block ? content_block.call : ""
|
56
55
|
end
|
57
56
|
|
58
57
|
def create_context(name, value)
|
@@ -66,40 +65,13 @@ module Rbexy
|
|
66
65
|
raise(ContextNotFound, "no parent context `#{name}`")
|
67
66
|
end
|
68
67
|
|
69
|
-
def
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
def component_name
|
74
|
-
self.class.name.underscore
|
68
|
+
def compiled_method_container
|
69
|
+
Rbexy::Component
|
75
70
|
end
|
76
71
|
|
77
72
|
private
|
78
73
|
|
79
|
-
attr_reader :view_context, :content_block
|
80
|
-
|
81
|
-
def replace_lookup_context
|
82
|
-
unless view_renderer.lookup_context.is_a? Rbexy::Component::LookupContext
|
83
|
-
@old_lookup_context = view_renderer.lookup_context
|
84
|
-
view_renderer.lookup_context = build_lookup_context(old_lookup_context)
|
85
|
-
end
|
86
|
-
|
87
|
-
(view_renderer.lookup_context.component_name_stack ||= []) << component_name
|
88
|
-
end
|
89
|
-
|
90
|
-
def restore_lookup_context
|
91
|
-
return unless old_lookup_context
|
92
|
-
view_renderer.lookup_context = old_lookup_context
|
93
|
-
@old_lookup_context = nil
|
94
|
-
end
|
95
|
-
|
96
|
-
def build_lookup_context(existing_context)
|
97
|
-
paths = existing_context.view_paths.dup.unshift(
|
98
|
-
*Rbexy.configuration.template_paths.map { |p| ActionView::OptimizedFileSystemResolver.new(p) }
|
99
|
-
)
|
100
|
-
|
101
|
-
LookupContext.new(paths, LookupContext.details_hash(existing_context))
|
102
|
-
end
|
74
|
+
attr_reader :view_context, :content_block
|
103
75
|
|
104
76
|
def method_missing(meth, *args, &block)
|
105
77
|
if view_context.respond_to?(meth)
|
@@ -108,5 +80,10 @@ module Rbexy
|
|
108
80
|
super
|
109
81
|
end
|
110
82
|
end
|
83
|
+
|
84
|
+
def clean_template_backtrace(backtrace)
|
85
|
+
return backtrace if Rbexy.configuration.debug
|
86
|
+
BacktraceCleaner.new(backtrace).call
|
87
|
+
end
|
111
88
|
end
|
112
89
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Rbexy
|
2
|
+
class Component
|
3
|
+
class BacktraceCleaner
|
4
|
+
attr_reader :backtrace
|
5
|
+
|
6
|
+
def initialize(backtrace)
|
7
|
+
@backtrace = backtrace
|
8
|
+
@found_templates = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
backtrace
|
13
|
+
.reject(&method(:internal_implementation_detail?))
|
14
|
+
.map(&method(:strip_rbx_internals_block_mention))
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :found_templates
|
20
|
+
|
21
|
+
def internal_implementation_detail?(line)
|
22
|
+
if template = template_name_if_rbx_internals(line)
|
23
|
+
redundant_internal_block?(line, template)
|
24
|
+
else
|
25
|
+
internal_method_call?(line)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def internal_method_call?(line)
|
30
|
+
line =~ /lib\/rbexy\/.*\.rb/ ||
|
31
|
+
line =~ /lib\/action_view\/.*\.rb/ ||
|
32
|
+
line =~ /lib\/active_support\/notifications\.rb/
|
33
|
+
end
|
34
|
+
|
35
|
+
def redundant_internal_block?(line, template)
|
36
|
+
if found_templates[template]
|
37
|
+
true
|
38
|
+
else
|
39
|
+
found_templates[template] = true
|
40
|
+
false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def strip_rbx_internals_block_mention(line)
|
45
|
+
if template_name_if_rbx_internals(line)
|
46
|
+
line.gsub(/block (\(\d+ levels\))? ?in /, "")
|
47
|
+
else
|
48
|
+
line
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def template_name_if_rbx_internals(line)
|
53
|
+
if /\/(?<template>[^\/]*)\.rbx:\d+:in `(block |_)/ =~ line
|
54
|
+
template
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/rbexy/configuration.rb
CHANGED
data/lib/rbexy/lexer.rb
CHANGED
@@ -22,7 +22,7 @@ module Rbexy
|
|
22
22
|
text_content: /[^<{#]+/,
|
23
23
|
comment: /^\p{Blank}*#.*(\n|\z)/,
|
24
24
|
whitespace: /\s+/,
|
25
|
-
attr: /[A-Za-z0-9\-_
|
25
|
+
attr: /[A-Za-z0-9\-_\.:]+/,
|
26
26
|
open_attr_splat: /{\*\*/,
|
27
27
|
attr_assignment: /=/,
|
28
28
|
double_quote: /"/,
|
@@ -237,7 +237,6 @@ module Rbexy
|
|
237
237
|
end
|
238
238
|
|
239
239
|
def potential_expression_inner_tag
|
240
|
-
# binding.pry
|
241
240
|
if self.curr_expr =~ Patterns.expression_internal_tag_prefixes
|
242
241
|
tokens << [:EXPRESSION_BODY, curr_expr]
|
243
242
|
self.curr_expr = ""
|
data/lib/rbexy/nodes.rb
CHANGED
@@ -18,11 +18,7 @@ module Rbexy
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def compile
|
21
|
-
|
22
|
-
"Rbexy::OutputBuffer.new.tap { |output|",
|
23
|
-
children.map(&:compile).map { |c| "output << (#{c})"}.join(";"),
|
24
|
-
"}.html_safe"
|
25
|
-
].join(" ")
|
21
|
+
"#{children.map(&:compile).map { |c| "@output_buffer << rbexy_prep_output(#{c})"}.join(";")};@output_buffer"
|
26
22
|
end
|
27
23
|
end
|
28
24
|
|
@@ -75,23 +71,24 @@ module Rbexy
|
|
75
71
|
base_tag = "rbexy_tag.#{Util.safe_tag_name(name)}(#{compile_members})"
|
76
72
|
tag = if children.length > 0
|
77
73
|
[
|
78
|
-
"#{base_tag} {",
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
"}"
|
83
|
-
].join(" ")
|
74
|
+
"#{base_tag} { capture {",
|
75
|
+
children.map(&:compile).map { |c| "@output_buffer << rbexy_prep_output(#{c})" }.join(";"),
|
76
|
+
"} }"
|
77
|
+
].join
|
84
78
|
else
|
85
79
|
base_tag
|
86
|
-
end
|
80
|
+
end + ".html_safe"
|
87
81
|
|
88
|
-
|
89
|
-
|
90
|
-
"
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
82
|
+
if Rbexy.configuration.enable_context
|
83
|
+
[
|
84
|
+
"(",
|
85
|
+
"rbexy_context.push({});",
|
86
|
+
"#{tag}.tap { rbexy_context.pop }",
|
87
|
+
")"
|
88
|
+
].join
|
89
|
+
else
|
90
|
+
tag
|
91
|
+
end
|
95
92
|
end
|
96
93
|
|
97
94
|
def compile_members
|
data/lib/rbexy/rails.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
require "action_view"
|
2
|
+
|
3
|
+
module Rbexy
|
4
|
+
module Rails
|
5
|
+
class ComponentTemplateResolver < ActionView::FileSystemResolver
|
6
|
+
# Rails 6 requires us to override `_find_all` in order to hook
|
7
|
+
def _find_all(name, prefix, partial, details, key, locals)
|
8
|
+
find_templates(name, prefix, partial, details, locals)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Rails 5 only requires `find_templates` (which tbh is the proper way
|
12
|
+
# to implement subclasses of ActionView::Resolver)
|
13
|
+
def find_templates(name, prefix, partial, details, locals = [])
|
14
|
+
return [] unless name.is_a? Rbexy::Component::TemplatePath
|
15
|
+
|
16
|
+
templates_path = File.join(@path, prefix, name)
|
17
|
+
extensions = details[:handlers].join(",")
|
18
|
+
|
19
|
+
Dir["#{templates_path}.*{#{extensions}}"].map do |template_path|
|
20
|
+
source = File.binread(template_path)
|
21
|
+
handler = ActionView::Template.handler_for_extension(File.extname(template_path)[1..-1])
|
22
|
+
virtual_path = ["rbexy_component", prefix, name].join("/")
|
23
|
+
|
24
|
+
ActionView::Template.new(
|
25
|
+
source,
|
26
|
+
template_path,
|
27
|
+
handler,
|
28
|
+
locals: [],
|
29
|
+
virtual_path: virtual_path
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "active_support/concern"
|
2
|
+
|
3
|
+
module Rbexy
|
4
|
+
module Rails
|
5
|
+
module ControllerHelper
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
def rbexy_component_provider; end
|
9
|
+
|
10
|
+
class_methods do
|
11
|
+
def inherited(klass)
|
12
|
+
super
|
13
|
+
Rbexy.configuration.template_paths.each do |path|
|
14
|
+
prepend_view_path(Rbexy::Rails::ComponentTemplateResolver.new(path))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/rbexy/rails/engine.rb
CHANGED
@@ -13,8 +13,7 @@ module Rbexy
|
|
13
13
|
ActiveSupport.on_load :action_controller_base do
|
14
14
|
helper Rbexy::ViewContextHelper
|
15
15
|
helper_method :rbexy_component_provider
|
16
|
-
|
17
|
-
def rbexy_component_provider; end
|
16
|
+
include ControllerHelper
|
18
17
|
end
|
19
18
|
|
20
19
|
if defined?(ViewComponent)
|
@@ -25,6 +24,7 @@ module Rbexy
|
|
25
24
|
require "rbexy/component_providers/rbexy_provider"
|
26
25
|
config.component_provider = Rbexy::ComponentProviders::RbexyProvider.new
|
27
26
|
config.template_paths << ::Rails.root.join("app", "components")
|
27
|
+
config.enable_context = true
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
data/lib/rbexy/runtime.rb
CHANGED
data/lib/rbexy/version.rb
CHANGED
@@ -7,5 +7,17 @@ module Rbexy
|
|
7
7
|
def rbexy_context
|
8
8
|
@rbexy_context ||= [{}]
|
9
9
|
end
|
10
|
+
|
11
|
+
def rbexy_prep_output(*value)
|
12
|
+
return if value.length == 0
|
13
|
+
value = value.first
|
14
|
+
|
15
|
+
value = rbexy_is_html_safe_array?(value) ? value.join.html_safe : value
|
16
|
+
[nil, false].include?(value) ? "" : value.to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
def rbexy_is_html_safe_array?(value)
|
20
|
+
value.is_a?(Array) && value.all? { |v| v.respond_to?(:html_safe?) && v.html_safe? }
|
21
|
+
end
|
10
22
|
end
|
11
23
|
end
|
data/rbexy.gemspec
CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_dependency "actionview", ">= 5.0", "< 7.0"
|
30
30
|
spec.add_dependency "railties", ">= 5.0", "< 7.0"
|
31
31
|
|
32
|
-
spec.add_development_dependency "rails", ">=
|
32
|
+
spec.add_development_dependency "rails", ">= 6.0", "< 7.0"
|
33
33
|
spec.add_development_dependency "rspec", "~> 3.9"
|
34
34
|
spec.add_development_dependency "guard-rspec", "~> 4.7", ">= 4.7.3"
|
35
35
|
spec.add_development_dependency "rspec-rails", "~> 4.0", ">= 4.0.1"
|
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: 0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Giancola
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -76,7 +76,7 @@ dependencies:
|
|
76
76
|
requirements:
|
77
77
|
- - ">="
|
78
78
|
- !ruby/object:Gem::Version
|
79
|
-
version: '
|
79
|
+
version: '6.0'
|
80
80
|
- - "<"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '7.0'
|
@@ -86,7 +86,7 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '6.0'
|
90
90
|
- - "<"
|
91
91
|
- !ruby/object:Gem::Version
|
92
92
|
version: '7.0'
|
@@ -224,6 +224,7 @@ files:
|
|
224
224
|
- example.rb
|
225
225
|
- lib/rbexy.rb
|
226
226
|
- lib/rbexy/component.rb
|
227
|
+
- lib/rbexy/component/backtrace_cleaner.rb
|
227
228
|
- lib/rbexy/component_providers/namespaced_rbexy_provider.rb
|
228
229
|
- lib/rbexy/component_providers/rbexy_provider.rb
|
229
230
|
- lib/rbexy/component_providers/view_component_provider.rb
|
@@ -232,9 +233,10 @@ files:
|
|
232
233
|
- lib/rbexy/hash_mash.rb
|
233
234
|
- lib/rbexy/lexer.rb
|
234
235
|
- lib/rbexy/nodes.rb
|
235
|
-
- lib/rbexy/output_buffer.rb
|
236
236
|
- lib/rbexy/parser.rb
|
237
237
|
- lib/rbexy/rails.rb
|
238
|
+
- lib/rbexy/rails/component_template_resolver.rb
|
239
|
+
- lib/rbexy/rails/controller_helper.rb
|
238
240
|
- lib/rbexy/rails/engine.rb
|
239
241
|
- lib/rbexy/runtime.rb
|
240
242
|
- lib/rbexy/version.rb
|