rbexy 1.1.0 → 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 +3 -1
- data/README.md +19 -1
- data/lib/rbexy.rb +26 -9
- data/lib/rbexy/ast_transformer.rb +21 -0
- data/lib/rbexy/cache_component.rb +17 -0
- data/lib/rbexy/component.rb +35 -21
- data/lib/rbexy/component_resolver.rb +60 -0
- data/lib/rbexy/configuration.rb +18 -1
- data/lib/rbexy/lexer.rb +21 -14
- data/lib/rbexy/nodes.rb +15 -135
- data/lib/rbexy/nodes/abstract_attr.rb +12 -0
- data/lib/rbexy/nodes/abstract_element.rb +13 -0
- data/lib/rbexy/nodes/abstract_node.rb +58 -0
- data/lib/rbexy/nodes/component_element.rb +69 -0
- data/lib/rbexy/nodes/component_prop.rb +29 -0
- data/lib/rbexy/nodes/declaration.rb +15 -0
- data/lib/rbexy/nodes/expression.rb +15 -0
- data/lib/rbexy/nodes/expression_group.rb +55 -0
- data/lib/rbexy/nodes/html_attr.rb +13 -0
- data/lib/rbexy/nodes/html_element.rb +48 -0
- data/lib/rbexy/nodes/newline.rb +9 -0
- data/lib/rbexy/nodes/raw.rb +23 -0
- data/lib/rbexy/nodes/root.rb +19 -0
- data/lib/rbexy/nodes/text.rb +15 -0
- data/lib/rbexy/nodes/util.rb +9 -0
- data/lib/rbexy/parser.rb +22 -16
- data/lib/rbexy/rails.rb +2 -0
- data/lib/rbexy/rails/component_template_resolver.rb +59 -4
- data/lib/rbexy/rails/controller_helper.rb +0 -6
- data/lib/rbexy/rails/engine.rb +3 -7
- data/lib/rbexy/rails/rbx_dependency_tracker.rb +37 -0
- data/lib/rbexy/refinements.rb +5 -0
- data/lib/rbexy/refinements/array.rb +9 -0
- data/lib/rbexy/refinements/array/find_map.rb +13 -0
- data/lib/rbexy/refinements/array/insert_between_types.rb +26 -0
- data/lib/rbexy/refinements/array/map_type_when_neighboring_type.rb +26 -0
- data/lib/rbexy/runtime.rb +15 -23
- data/lib/rbexy/template.rb +12 -0
- data/lib/rbexy/version.rb +1 -1
- data/rbexy.gemspec +1 -0
- metadata +43 -11
- data/example.rb +0 -113
- data/lib/rbexy/component_providers/namespaced_rbexy_provider.rb +0 -20
- data/lib/rbexy/component_providers/rbexy_provider.rb +0 -21
- data/lib/rbexy/component_providers/view_component_provider.rb +0 -21
- data/lib/rbexy/component_tag_builder.rb +0 -19
- data/lib/rbexy/hash_mash.rb +0 -15
- data/lib/rbexy/view_context_helper.rb +0 -19
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
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rbexy (
|
4
|
+
rbexy (2.0.0.beta5)
|
5
5
|
actionview (>= 6.0, < 7.0)
|
6
6
|
activesupport (>= 6.0, < 7.0)
|
7
7
|
|
@@ -101,6 +101,7 @@ GEM
|
|
101
101
|
mini_mime (>= 0.1.1)
|
102
102
|
marcel (0.3.3)
|
103
103
|
mimemagic (~> 0.3.2)
|
104
|
+
memory_profiler (0.9.14)
|
104
105
|
method_source (1.0.0)
|
105
106
|
mimemagic (0.3.5)
|
106
107
|
mini_mime (1.0.2)
|
@@ -199,6 +200,7 @@ PLATFORMS
|
|
199
200
|
|
200
201
|
DEPENDENCIES
|
201
202
|
guard-rspec (~> 4.7, >= 4.7.3)
|
203
|
+
memory_profiler (~> 0.9.14)
|
202
204
|
pry-byebug
|
203
205
|
rails (>= 6.0, < 7.0)
|
204
206
|
rake
|
data/README.md
CHANGED
@@ -173,6 +173,14 @@ Loops:
|
|
173
173
|
</ul>
|
174
174
|
```
|
175
175
|
|
176
|
+
Blocks:
|
177
|
+
|
178
|
+
```jsx
|
179
|
+
{link_to "/" do
|
180
|
+
<span>Click me</span>
|
181
|
+
end}
|
182
|
+
```
|
183
|
+
|
176
184
|
As an attribute:
|
177
185
|
|
178
186
|
```jsx
|
@@ -189,6 +197,16 @@ Pass a lambda to a prop, that when called returns a tag:
|
|
189
197
|
</Hero>
|
190
198
|
```
|
191
199
|
|
200
|
+
_Note that when using tags inside blocks, the block must evaluate to a single root element. Rbexy behaves similar to JSX in this way. E.g.:_
|
201
|
+
|
202
|
+
```
|
203
|
+
# Do
|
204
|
+
-> { <span><i>Hello</i> World</span> }
|
205
|
+
|
206
|
+
# Don't
|
207
|
+
-> { <i>Hello</i> World }
|
208
|
+
```
|
209
|
+
|
192
210
|
### Tags
|
193
211
|
|
194
212
|
You can put standard HTML tags anywhere.
|
@@ -283,7 +301,7 @@ By default, we'll look for a template file in the same directory as the class an
|
|
283
301
|
<h1>{@title}</h1>
|
284
302
|
```
|
285
303
|
|
286
|
-
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`.
|
287
305
|
|
288
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/`.
|
289
307
|
|
data/lib/rbexy.rb
CHANGED
@@ -1,15 +1,22 @@
|
|
1
1
|
require "rbexy/version"
|
2
|
+
require "active_support/inflector"
|
3
|
+
require "active_support/concern"
|
4
|
+
require "action_view/helpers/output_safety_helper"
|
5
|
+
require "action_view/helpers/capture_helper"
|
6
|
+
require "action_view/helpers/tag_helper"
|
7
|
+
require "action_view/context"
|
2
8
|
|
3
9
|
module Rbexy
|
4
10
|
autoload :Lexer, "rbexy/lexer"
|
5
11
|
autoload :Parser, "rbexy/parser"
|
6
12
|
autoload :Nodes, "rbexy/nodes"
|
7
13
|
autoload :Runtime, "rbexy/runtime"
|
8
|
-
autoload :HashMash, "rbexy/hash_mash"
|
9
|
-
autoload :ComponentTagBuilder, "rbexy/component_tag_builder"
|
10
|
-
autoload :ViewContextHelper, "rbexy/view_context_helper"
|
11
14
|
autoload :ComponentContext, "rbexy/component_context"
|
12
15
|
autoload :Configuration, "rbexy/configuration"
|
16
|
+
autoload :ComponentResolver, "rbexy/component_resolver"
|
17
|
+
autoload :Template, "rbexy/template"
|
18
|
+
autoload :Refinements, "rbexy/refinements"
|
19
|
+
autoload :ASTTransformer, "rbexy/ast_transformer"
|
13
20
|
|
14
21
|
ContextNotFound = Class.new(StandardError)
|
15
22
|
|
@@ -22,14 +29,24 @@ module Rbexy
|
|
22
29
|
@configuration ||= Configuration.new
|
23
30
|
end
|
24
31
|
|
25
|
-
def compile(
|
26
|
-
tokens =
|
27
|
-
|
28
|
-
|
32
|
+
def compile(template, context = build_default_compile_context(template))
|
33
|
+
tokens = Lexer.new(template, context.element_resolver).tokenize
|
34
|
+
root = Parser.new(tokens).parse
|
35
|
+
root.inject_compile_context(context)
|
36
|
+
root.transform!
|
37
|
+
root.precompile.compile
|
29
38
|
end
|
30
39
|
|
31
|
-
def evaluate(template_string, runtime)
|
32
|
-
runtime.evaluate compile(template_string)
|
40
|
+
def evaluate(template_string, runtime = Rbexy::Runtime.new)
|
41
|
+
runtime.evaluate compile(Template.new(template_string))
|
42
|
+
end
|
43
|
+
|
44
|
+
def build_default_compile_context(template)
|
45
|
+
OpenStruct.new(
|
46
|
+
template: template,
|
47
|
+
element_resolver: configuration.element_resolver,
|
48
|
+
ast_transformer: configuration.transforms
|
49
|
+
)
|
33
50
|
end
|
34
51
|
end
|
35
52
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Rbexy
|
2
|
+
class ASTTransformer
|
3
|
+
attr_reader :registry
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
clear!
|
7
|
+
end
|
8
|
+
|
9
|
+
def register(*node_classes, &block)
|
10
|
+
node_classes.each { |k| (registry[k] ||= []) << block }
|
11
|
+
end
|
12
|
+
|
13
|
+
def transform(node, context)
|
14
|
+
registry[node.class]&.each { |t| t.call(node, context) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def clear!
|
18
|
+
@registry = {}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -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
@@ -11,12 +11,22 @@ module Rbexy
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
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)
|
16
22
|
end
|
17
23
|
|
18
|
-
def
|
19
|
-
|
24
|
+
def self.call_component?
|
25
|
+
method_defined?(:call)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.component_name
|
29
|
+
name.underscore
|
20
30
|
end
|
21
31
|
|
22
32
|
def initialize(view_context, **props)
|
@@ -28,7 +38,7 @@ module Rbexy
|
|
28
38
|
|
29
39
|
@view_context = view_context
|
30
40
|
|
31
|
-
|
41
|
+
after_initialize(**props)
|
32
42
|
end
|
33
43
|
|
34
44
|
# Override in your subclass to handle props, setup your component, etc.
|
@@ -36,18 +46,9 @@ module Rbexy
|
|
36
46
|
# call super(view_context).
|
37
47
|
def setup(**props); end
|
38
48
|
|
39
|
-
def
|
49
|
+
def render_in(_context = view_context, &block)
|
40
50
|
@content_block = block_given? ? block : nil
|
41
|
-
call
|
42
|
-
end
|
43
|
-
|
44
|
-
def call
|
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
|
51
|
+
self.class.call_component? ? call : _render
|
51
52
|
end
|
52
53
|
|
53
54
|
def content
|
@@ -62,17 +63,30 @@ module Rbexy
|
|
62
63
|
|
63
64
|
attr_reader :view_context, :content_block
|
64
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
|
+
|
65
75
|
def method_missing(meth, *args, &block)
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
76
|
+
view_context.send(meth, *args, &block)
|
77
|
+
end
|
78
|
+
|
79
|
+
def respond_to_missing?(method_name, include_all)
|
80
|
+
view_context.respond_to?(method_name, include_all)
|
71
81
|
end
|
72
82
|
|
73
83
|
def clean_template_backtrace(backtrace)
|
74
84
|
return backtrace if Rbexy.configuration.debug
|
75
85
|
BacktraceCleaner.new(backtrace).call
|
76
86
|
end
|
87
|
+
|
88
|
+
def after_initialize(**props)
|
89
|
+
setup(**props)
|
90
|
+
end
|
77
91
|
end
|
78
92
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Rbexy
|
2
|
+
class ComponentResolver
|
3
|
+
using Rbexy::Refinements::Array::FindMap
|
4
|
+
|
5
|
+
KNOWN_HTML_ELEMENTS = %w(
|
6
|
+
a abbr acronym address animate animateMotion animateTransform applet area article aside audio b base basefont
|
7
|
+
bdi bdo bgsound big blink blockquote body br button canvas caption center circle cite clipPath code col colgroup
|
8
|
+
color-profile command content data datalist dd defs del desc details dfn dialog dir discard div dl dt element
|
9
|
+
ellipse em embed feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting
|
10
|
+
feDisplacementMap feDistantLight feDropShadow feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage
|
11
|
+
feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence
|
12
|
+
fieldset figcaption figure filter font footer foreignObject form frame frameset g h1 h2 h3 h4 h5 h6 hatch
|
13
|
+
hatchpath head header hgroup hr html i iframe image img input ins isindex kbd keygen label legend li line
|
14
|
+
linearGradient link listing main map mark marker marquee mask menu menuitem mesh meshgradient meshpatch meshrow
|
15
|
+
meta metadata meter mpath multicol nav nextid nobr noembed noframes noscript object ol optgroup option output p
|
16
|
+
param path pattern picture plaintext polygon polyline pre progress q radialGradient rb rect rp rt rtc ruby s
|
17
|
+
samp script section select set shadow slot small solidcolor source spacer span stop strike strong style sub
|
18
|
+
summary sup svg switch symbol table tbody td template text textarea textPath tfoot th thead time title tr track
|
19
|
+
tspan tt u ul unknown use var video view wbr xmp
|
20
|
+
).to_set
|
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
|
+
|
29
|
+
attr_reader :component_namespaces
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
self.component_namespaces = {}
|
33
|
+
end
|
34
|
+
|
35
|
+
def component_namespaces=(hash)
|
36
|
+
@component_namespaces = hash.transform_keys(&:to_s)
|
37
|
+
end
|
38
|
+
|
39
|
+
def component?(name, template)
|
40
|
+
return false if KNOWN_HTML_ELEMENTS.include?(name)
|
41
|
+
return true if component_class(name, template)
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
def component_class(name, template)
|
46
|
+
possible_names = matching_namespaces(template).map { |ns| "#{ns}.#{name}" } << name
|
47
|
+
possible_names.find_map(&method(:find))
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def find(name)
|
53
|
+
self.class.try_constantize { ActiveSupport::Inflector.constantize("#{name.gsub(".", "::")}Component") }
|
54
|
+
end
|
55
|
+
|
56
|
+
def matching_namespaces(template)
|
57
|
+
component_namespaces.select { |path, ns| template.identifier.start_with?(path) }.values.flatten.uniq
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/rbexy/configuration.rb
CHANGED
@@ -1,12 +1,29 @@
|
|
1
1
|
module Rbexy
|
2
2
|
class Configuration
|
3
|
-
attr_accessor :
|
3
|
+
attr_accessor :element_resolver
|
4
4
|
attr_accessor :template_paths
|
5
5
|
attr_accessor :enable_context
|
6
6
|
attr_accessor :debug
|
7
|
+
attr_accessor :component_rendering_templates
|
8
|
+
attr_accessor :transforms
|
7
9
|
|
8
10
|
def template_paths
|
9
11
|
@template_paths ||= []
|
10
12
|
end
|
13
|
+
|
14
|
+
def element_resolver
|
15
|
+
@element_resolver ||= ComponentResolver.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def transforms
|
19
|
+
@transforms ||= ASTTransformer.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def component_rendering_templates
|
23
|
+
@component_rendering_templates ||= {
|
24
|
+
children: "{capture{%{children}}}",
|
25
|
+
component: "::%{component_class}.new(%{view_context},%{kwargs}).render_in%{children_block}"
|
26
|
+
}
|
27
|
+
end
|
11
28
|
end
|
12
29
|
end
|
data/lib/rbexy/lexer.rb
CHANGED
@@ -10,7 +10,7 @@ module Rbexy
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
Patterns =
|
13
|
+
Patterns = OpenStruct.new(
|
14
14
|
open_expression: /{/,
|
15
15
|
close_expression: /}/,
|
16
16
|
expression_content: /[^}{"'<]+/,
|
@@ -29,23 +29,23 @@ module Rbexy
|
|
29
29
|
single_quote: /'/,
|
30
30
|
double_quoted_text_content: /[^"]+/,
|
31
31
|
single_quoted_text_content: /[^']+/,
|
32
|
-
expression_internal_tag_prefixes: /(\s+(
|
32
|
+
expression_internal_tag_prefixes: /(\s+(&&|\|\||\?|:|do|do\s*\|[^\|]+\||{|{\s*\|[^\|]+\|)\s+\z|\A\s*\z)/,
|
33
33
|
declaration: /<![^>]*>/
|
34
34
|
)
|
35
35
|
|
36
|
-
attr_reader :stack, :tokens, :scanner, :
|
37
|
-
attr_accessor :
|
36
|
+
attr_reader :stack, :tokens, :scanner, :element_resolver, :template
|
37
|
+
attr_accessor :curr_expr, :curr_default_text,
|
38
38
|
:curr_quoted_text
|
39
39
|
|
40
|
-
def initialize(
|
40
|
+
def initialize(template, element_resolver)
|
41
|
+
@template = template
|
42
|
+
@scanner = StringScanner.new(template.source)
|
43
|
+
@element_resolver = element_resolver
|
41
44
|
@stack = [:default]
|
42
|
-
@curr_expr_bracket_levels = 0
|
43
|
-
@curr_expr_quote_levels = { single: 0, double: 0 }
|
44
45
|
@curr_expr = ""
|
45
46
|
@curr_default_text = ""
|
46
47
|
@curr_quoted_text = ""
|
47
48
|
@tokens = []
|
48
|
-
@scanner = StringScanner.new(code)
|
49
49
|
end
|
50
50
|
|
51
51
|
def tokenize
|
@@ -59,7 +59,7 @@ module Rbexy
|
|
59
59
|
elsif scanner.scan(Patterns.open_expression)
|
60
60
|
open_expression
|
61
61
|
elsif scanner.scan(Patterns.comment)
|
62
|
-
tokens << [:
|
62
|
+
tokens << [:NEWLINE]
|
63
63
|
elsif scanner.check(Patterns.text_content)
|
64
64
|
stack.push(:default_text)
|
65
65
|
else
|
@@ -74,7 +74,7 @@ module Rbexy
|
|
74
74
|
elsif scanner.scan(Patterns.open_expression)
|
75
75
|
open_expression
|
76
76
|
elsif scanner.scan(Patterns.comment)
|
77
|
-
tokens << [:
|
77
|
+
tokens << [:NEWLINE]
|
78
78
|
elsif scanner.check(Patterns.text_content)
|
79
79
|
stack.push(:default_text)
|
80
80
|
else
|
@@ -163,9 +163,9 @@ module Rbexy
|
|
163
163
|
tokens << [:CLOSE_TAG_DEF]
|
164
164
|
stack.pop
|
165
165
|
elsif scanner.scan(Patterns.tag_name)
|
166
|
-
tokens << [:
|
166
|
+
tokens << [:TAG_DETAILS, tag_details(scanner.matched)]
|
167
167
|
elsif scanner.scan(Patterns.whitespace)
|
168
|
-
scanner.matched.count("\n").times { tokens << [:
|
168
|
+
scanner.matched.count("\n").times { tokens << [:NEWLINE] }
|
169
169
|
tokens << [:OPEN_ATTRS]
|
170
170
|
stack.push(:tag_attrs)
|
171
171
|
else
|
@@ -182,7 +182,7 @@ module Rbexy
|
|
182
182
|
end
|
183
183
|
when :tag_attrs
|
184
184
|
if scanner.scan(Patterns.whitespace)
|
185
|
-
scanner.matched.count("\n").times { tokens << [:
|
185
|
+
scanner.matched.count("\n").times { tokens << [:NEWLINE] }
|
186
186
|
elsif scanner.check(Patterns.close_tag)
|
187
187
|
tokens << [:CLOSE_ATTRS]
|
188
188
|
stack.pop
|
@@ -205,7 +205,7 @@ module Rbexy
|
|
205
205
|
open_expression
|
206
206
|
elsif scanner.scan(Patterns.whitespace) || scanner.check(Patterns.close_tag)
|
207
207
|
tokens << [:CLOSE_ATTR_VALUE]
|
208
|
-
scanner.matched.count("\n").times { tokens << [:
|
208
|
+
scanner.matched.count("\n").times { tokens << [:NEWLINE] }
|
209
209
|
stack.pop
|
210
210
|
else
|
211
211
|
raise SyntaxError, self
|
@@ -286,5 +286,12 @@ module Rbexy
|
|
286
286
|
# etc).
|
287
287
|
scanner.scan(Patterns.expression_content) || scanner.scan(Patterns.open_tag_end)
|
288
288
|
end
|
289
|
+
|
290
|
+
def tag_details(name)
|
291
|
+
type = element_resolver.component?(name, template) ? :component : :html
|
292
|
+
details = { name: scanner.matched, type: type }
|
293
|
+
details[:component_class] = element_resolver.component_class(name, template) if type == :component
|
294
|
+
details
|
295
|
+
end
|
289
296
|
end
|
290
297
|
end
|