rbexy 1.1.0 → 2.0.0.beta5
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/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
         |