rblade 0.4.0 → 0.6.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/CHANGELOG.md +18 -1
- data/README.md +115 -517
- data/lib/rblade/compiler/compiles_components.rb +29 -11
- data/lib/rblade/compiler/compiles_echos.rb +4 -4
- data/lib/rblade/compiler/compiles_ruby.rb +1 -1
- data/lib/rblade/compiler/compiles_statements.rb +21 -13
- data/lib/rblade/compiler/statements/compiles_conditionals.rb +40 -0
- data/lib/rblade/compiler/statements/compiles_form.rb +48 -0
- data/lib/rblade/compiler/statements/compiles_props.rb +23 -4
- data/lib/rblade/compiler/statements/compiles_stacks.rb +39 -15
- data/lib/rblade/compiler/tokenizes_statements.rb +13 -2
- data/lib/rblade/compiler.rb +9 -0
- data/lib/rblade/component_store.rb +1 -1
- data/lib/rblade/helpers/attributes_manager.rb +37 -7
- data/lib/rblade/helpers/html_string.rb +4 -0
- data/lib/rblade/helpers/slot_manager.rb +31 -0
- data/lib/rblade/helpers/stack_manager.rb +4 -0
- data/lib/rblade/rails_template.rb +1 -0
- data/rblade.gemspec +1 -1
- metadata +9 -7
- data/TODO.md +0 -2
| @@ -26,17 +26,16 @@ module RBlade | |
| 26 26 | 
             
                private
         | 
| 27 27 |  | 
| 28 28 | 
             
                def compile_token_start token
         | 
| 29 | 
            -
                   | 
| 30 | 
            -
             | 
| 31 | 
            -
                  @component_stack << {
         | 
| 29 | 
            +
                  component = {
         | 
| 32 30 | 
             
                    name: token.value[:name],
         | 
| 33 | 
            -
                    index: @ | 
| 31 | 
            +
                    index: @component_stack.count
         | 
| 34 32 | 
             
                  }
         | 
| 33 | 
            +
                  @component_stack << component
         | 
| 35 34 |  | 
| 36 35 | 
             
                  attributes = compile_attributes token.value[:attributes]
         | 
| 37 36 |  | 
| 38 | 
            -
                  code = "_c#{ | 
| 39 | 
            -
                  code << "_c#{ | 
| 37 | 
            +
                  code = "_c#{component[:index]}_swap=_out;_out='';"
         | 
| 38 | 
            +
                  code << "_c#{component[:index]}_attr={#{attributes.join(",")}};"
         | 
| 40 39 |  | 
| 41 40 | 
             
                  code
         | 
| 42 41 | 
             
                end
         | 
| @@ -50,15 +49,34 @@ module RBlade | |
| 50 49 | 
             
                    raise StandardError.new "Unexpected closing tag (#{token.value[:name]}) expecting #{component[:name]}"
         | 
| 51 50 | 
             
                  end
         | 
| 52 51 |  | 
| 53 | 
            -
                   | 
| 54 | 
            -
                   | 
| 55 | 
            -
                   | 
| 52 | 
            +
                  namespace = nil
         | 
| 53 | 
            +
                  name = component[:name]
         | 
| 54 | 
            +
                  if name.match '::'
         | 
| 55 | 
            +
                    namespace, name = component[:name].split("::")
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                  code = if namespace == 'slot'
         | 
| 59 | 
            +
                    compile_slot_end name, component
         | 
| 60 | 
            +
                  else
         | 
| 61 | 
            +
                    compile_component_end component
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                def compile_slot_end name, component
         | 
| 66 | 
            +
                  parent = @component_stack.last
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                  code = "_c#{parent[:index]}_attr[:'#{RBlade.escape_quotes(name)}']=RBlade::SlotManager.new(_out,_c#{component[:index]}_attr);"
         | 
| 69 | 
            +
                  code << "_out=_c#{component[:index]}_swap;_c#{component[:index]}_swap=nil;_c#{component[:index]}_attr=nil;"
         | 
| 56 70 |  | 
| 57 71 | 
             
                  code
         | 
| 58 72 | 
             
                end
         | 
| 59 73 |  | 
| 60 | 
            -
                def  | 
| 61 | 
            -
                   | 
| 74 | 
            +
                def compile_component_end component
         | 
| 75 | 
            +
                  code = "_slot=RBlade::SlotManager.new(_out);_out=_c#{component[:index]}_swap;"
         | 
| 76 | 
            +
                  code << "_out<<#{ComponentStore.component(component[:name])}(_slot,_c#{component[:index]}_attr,params,session,flash,cookies);"
         | 
| 77 | 
            +
                  code << "_slot=nil;_c#{component[:index]}_swap=nil;_c#{component[:index]}_attr=nil;"
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  code
         | 
| 62 80 | 
             
                end
         | 
| 63 81 |  | 
| 64 82 | 
             
                def compile_attributes attributes
         | 
| @@ -8,8 +8,8 @@ module RBlade | |
| 8 8 | 
             
                private
         | 
| 9 9 |  | 
| 10 10 | 
             
                def compile_regular_echos!(tokens)
         | 
| 11 | 
            -
                  compile_echos! tokens, "{{", "}}", " | 
| 12 | 
            -
                  compile_echos! tokens, "<%=", "%>", " | 
| 11 | 
            +
                  compile_echos! tokens, "{{", "}}", "RBlade.e"
         | 
| 12 | 
            +
                  compile_echos! tokens, "<%=", "%>", "RBlade.e"
         | 
| 13 13 | 
             
                end
         | 
| 14 14 |  | 
| 15 15 | 
             
                def compile_unsafe_echos!(tokens)
         | 
| @@ -35,8 +35,8 @@ module RBlade | |
| 35 35 | 
             
                        segments.delete_at i
         | 
| 36 36 | 
             
                        segments.delete_at i + 1
         | 
| 37 37 | 
             
                        segment_value = "_out<<"
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                        segment_value <<= if !wrapper_function.nil? | 
| 38 | 
            +
             | 
| 39 | 
            +
                        segment_value <<= if !wrapper_function.nil?
         | 
| 40 40 | 
             
                          wrapper_function + "(" + segments[i] + ");"
         | 
| 41 41 | 
             
                        else
         | 
| 42 42 | 
             
                          "(" + segments[i] + ").to_s;"
         | 
| @@ -1,4 +1,5 @@ | |
| 1 1 | 
             
            require "rblade/compiler/statements/compiles_conditionals"
         | 
| 2 | 
            +
            require "rblade/compiler/statements/compiles_form"
         | 
| 2 3 | 
             
            require "rblade/compiler/statements/compiles_html_attributes"
         | 
| 3 4 | 
             
            require "rblade/compiler/statements/compiles_inline_ruby"
         | 
| 4 5 | 
             
            require "rblade/compiler/statements/compiles_loops"
         | 
| @@ -48,7 +49,12 @@ module RBlade | |
| 48 49 | 
             
                  handler_class, handler_method = @@statement_handlers[name.tr("_", "").downcase]
         | 
| 49 50 |  | 
| 50 51 | 
             
                  if !handler_class&.method_defined?(handler_method)
         | 
| 51 | 
            -
                     | 
| 52 | 
            +
                    if name.start_with? "end"
         | 
| 53 | 
            +
                      ## Fallback to the default end handler
         | 
| 54 | 
            +
                      handler_class, handler_method = @@statement_handlers["end"]
         | 
| 55 | 
            +
                    else
         | 
| 56 | 
            +
                      raise StandardError.new "Unhandled statement: @#{name}"
         | 
| 57 | 
            +
                    end
         | 
| 52 58 | 
             
                  end
         | 
| 53 59 |  | 
| 54 60 | 
             
                  if handler_class == CompilesStatements
         | 
| @@ -63,47 +69,49 @@ module RBlade | |
| 63 69 | 
             
                @@handler_instances = {}
         | 
| 64 70 |  | 
| 65 71 | 
             
                @@statement_handlers = {
         | 
| 72 | 
            +
                  "blank?" => [CompilesConditionals, :compileBlank],
         | 
| 66 73 | 
             
                  "break" => [CompilesLoops, :compileBreak],
         | 
| 67 74 | 
             
                  "breakif" => [CompilesLoops, :compileBreakIf],
         | 
| 68 75 | 
             
                  "case" => [CompilesConditionals, :compileCase],
         | 
| 69 76 | 
             
                  "checked" => [CompilesConditionals, :compileChecked],
         | 
| 70 77 | 
             
                  "class" => [CompilesHtmlAttributes, :compileClass],
         | 
| 78 | 
            +
                  "defined?" => [CompilesConditionals, :compileDefined],
         | 
| 79 | 
            +
                  "delete" => [CompilesForm, :compileDelete],
         | 
| 71 80 | 
             
                  "disabled" => [CompilesConditionals, :compileDisabled],
         | 
| 72 81 | 
             
                  "else" => [CompilesConditionals, :compileElse],
         | 
| 73 82 | 
             
                  "elsif" => [CompilesConditionals, :compileElsif],
         | 
| 74 83 | 
             
                  "each" => [CompilesLoops, :compileEach],
         | 
| 75 84 | 
             
                  "eachelse" => [CompilesLoops, :compileEachElse],
         | 
| 76 85 | 
             
                  "empty" => [CompilesLoops, :compileEmpty],
         | 
| 86 | 
            +
                  "empty?" => [CompilesConditionals, :compileEmpty],
         | 
| 77 87 | 
             
                  "end" => [CompilesStatements, :compileEnd],
         | 
| 78 | 
            -
                  "endcase" => [CompilesStatements, :compileEnd],
         | 
| 79 | 
            -
                  "endeach" => [CompilesStatements, :compileEnd],
         | 
| 80 | 
            -
                  "endeachelse" => [CompilesStatements, :compileEnd],
         | 
| 81 | 
            -
                  "endenv" => [CompilesStatements, :compileEnd],
         | 
| 82 | 
            -
                  "endfor" => [CompilesStatements, :compileEnd],
         | 
| 83 | 
            -
                  "endforelse" => [CompilesStatements, :compileEnd],
         | 
| 84 | 
            -
                  "endif" => [CompilesStatements, :compileEnd],
         | 
| 85 | 
            -
                  "endonce" => [CompilesStatements, :compileEnd],
         | 
| 86 88 | 
             
                  "endprepend" => [CompilesStacks, :compileEndPrepend],
         | 
| 89 | 
            +
                  "endprependif" => [CompilesStacks, :compileEndPrependIf],
         | 
| 87 90 | 
             
                  "endprependonce" => [CompilesOnce, :compileEndPrependOnce],
         | 
| 88 | 
            -
                  "endproduction" => [CompilesStatements, :compileEnd],
         | 
| 89 91 | 
             
                  "endpush" => [CompilesStacks, :compileEndPush],
         | 
| 92 | 
            +
                  "endpushif" => [CompilesStacks, :compileEndPushIf],
         | 
| 90 93 | 
             
                  "endpushonce" => [CompilesOnce, :compileEndPushOnce],
         | 
| 91 | 
            -
                  "endunless" => [CompilesStatements, :compileEnd],
         | 
| 92 | 
            -
                  "enduntil" => [CompilesStatements, :compileEnd],
         | 
| 93 | 
            -
                  "endwhile" => [CompilesStatements, :compileEnd],
         | 
| 94 94 | 
             
                  "env" => [CompilesConditionals, :compileEnv],
         | 
| 95 95 | 
             
                  "for" => [CompilesLoops, :compileFor],
         | 
| 96 96 | 
             
                  "forelse" => [CompilesLoops, :compileForElse],
         | 
| 97 97 | 
             
                  "if" => [CompilesConditionals, :compileIf],
         | 
| 98 | 
            +
                  "method" => [CompilesForm, :compileMethod],
         | 
| 98 99 | 
             
                  "next" => [CompilesLoops, :compileNext],
         | 
| 99 100 | 
             
                  "nextif" => [CompilesLoops, :compileNextIf],
         | 
| 101 | 
            +
                  "nil?" => [CompilesConditionals, :compileNil],
         | 
| 102 | 
            +
                  "old" => [CompilesForm, :compileOld],
         | 
| 100 103 | 
             
                  "once" => [CompilesOnce, :compileOnce],
         | 
| 104 | 
            +
                  "patch" => [CompilesForm, :compilePatch],
         | 
| 101 105 | 
             
                  "prepend" => [CompilesStacks, :compilePrepend],
         | 
| 106 | 
            +
                  "prependif" => [CompilesStacks, :compilePrependIf],
         | 
| 102 107 | 
             
                  "prependonce" => [CompilesOnce, :compilePrependOnce],
         | 
| 108 | 
            +
                  "present?" => [CompilesConditionals, :compilePresent],
         | 
| 103 109 | 
             
                  "production" => [CompilesConditionals, :compileProduction],
         | 
| 104 110 | 
             
                  "props" => [CompilesProps, :compileProps],
         | 
| 105 111 | 
             
                  "push" => [CompilesStacks, :compilePush],
         | 
| 112 | 
            +
                  "pushif" => [CompilesStacks, :compilePushIf],
         | 
| 106 113 | 
             
                  "pushonce" => [CompilesOnce, :compilePushOnce],
         | 
| 114 | 
            +
                  "put" => [CompilesForm, :compilePut],
         | 
| 107 115 | 
             
                  "readonly" => [CompilesConditionals, :compileReadonly],
         | 
| 108 116 | 
             
                  "required" => [CompilesConditionals, :compileRequired],
         | 
| 109 117 | 
             
                  "ruby" => [CompilesInlineRuby, :compile],
         | 
| @@ -9,6 +9,46 @@ module RBlade | |
| 9 9 | 
             
                    "if #{args[0]};"
         | 
| 10 10 | 
             
                  end
         | 
| 11 11 |  | 
| 12 | 
            +
                  def compileBlank args
         | 
| 13 | 
            +
                    if args&.count != 1
         | 
| 14 | 
            +
                      raise StandardError.new "Blank? statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    "if (#{args[0]}).blank?;"
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def compileDefined args
         | 
| 21 | 
            +
                    if args&.count != 1
         | 
| 22 | 
            +
                      raise StandardError.new "Defined? statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    "if defined? #{args[0]};"
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def compileEmpty args
         | 
| 29 | 
            +
                    if args&.count != 1
         | 
| 30 | 
            +
                      raise StandardError.new "Empty? statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    "if (#{args[0]}).empty?;"
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  def compileNil args
         | 
| 37 | 
            +
                    if args&.count != 1
         | 
| 38 | 
            +
                      raise StandardError.new "Nil? statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    "if (#{args[0]}).nil?;"
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def compilePresent args
         | 
| 45 | 
            +
                    if args&.count != 1
         | 
| 46 | 
            +
                      raise StandardError.new "Present? statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    "if (#{args[0]}).present?;"
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 12 52 | 
             
                  def compileElsif args
         | 
| 13 53 | 
             
                    if args&.count != 1
         | 
| 14 54 | 
             
                      raise StandardError.new "Elsif statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            module RBlade
         | 
| 2 | 
            +
              class CompilesStatements
         | 
| 3 | 
            +
                class CompilesForm
         | 
| 4 | 
            +
                  def compileMethod args
         | 
| 5 | 
            +
                    if args&.count != 1
         | 
| 6 | 
            +
                      raise StandardError.new "Once statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
         | 
| 7 | 
            +
                    end
         | 
| 8 | 
            +
                    method = RBlade.h(args[0].tr "\"'", "")
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    %[_out<<'<input type="hidden" name="_method" value="#{method}">';]
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def compileDelete args
         | 
| 14 | 
            +
                    if !args.nil?
         | 
| 15 | 
            +
                      raise StandardError.new "Once statement: wrong number of arguments (given #{args.count}, expecting 0)"
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    compileMethod(['DELETE'])
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def compilePatch args
         | 
| 22 | 
            +
                    if !args.nil?
         | 
| 23 | 
            +
                      raise StandardError.new "Once statement: wrong number of arguments (given #{args.count}, expecting 0)"
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    compileMethod(['PATCH'])
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  def compilePut args
         | 
| 30 | 
            +
                    if !args.nil?
         | 
| 31 | 
            +
                      raise StandardError.new "Once statement: wrong number of arguments (given #{args.count}, expecting 0)"
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    compileMethod(['PUT'])
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def compileOld args
         | 
| 38 | 
            +
                    if args.nil? || args.count > 2
         | 
| 39 | 
            +
                      raise StandardError.new "Once statement: wrong number of arguments (given #{args.count}, expecting 0)"
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    default_value = args[1] || "''"
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    "_out<<params.fetch(#{args[0]},#{default_value});"
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         | 
| @@ -10,14 +10,23 @@ module RBlade | |
| 10 10 |  | 
| 11 11 | 
             
                    props = extractProps args[0]
         | 
| 12 12 | 
             
                    props.map do |key, value|
         | 
| 13 | 
            +
                      compiled_code = ""
         | 
| 13 14 | 
             
                      if value == "_required"
         | 
| 14 | 
            -
                        "if ! | 
| 15 | 
            +
                        compiled_code << "if !attributes.has?(:'#{RBlade.escape_quotes(key)}');raise \"Props statement: #{key} is not defined\";end;"
         | 
| 16 | 
            +
                      end
         | 
| 17 | 
            +
                      if isValidVariableName key
         | 
| 18 | 
            +
                        compiled_code << "#{key}=attributes[:'#{RBlade.escape_quotes(key)}'].nil? ? #{value} : attributes[:'#{RBlade.escape_quotes(key)}'];"
         | 
| 19 | 
            +
                        compiled_code << "attributes.delete :'#{RBlade.escape_quotes(key)}';"
         | 
| 15 20 | 
             
                      else
         | 
| 16 | 
            -
                         | 
| 21 | 
            +
                        compiled_code << "attributes.default(:'#{RBlade.escape_quotes(key)}', #{value});"
         | 
| 17 22 | 
             
                      end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                      compiled_code
         | 
| 18 25 | 
             
                    end.join
         | 
| 19 26 | 
             
                  end
         | 
| 20 27 |  | 
| 28 | 
            +
                  private
         | 
| 29 | 
            +
             | 
| 21 30 | 
             
                  def extractProps prop_string
         | 
| 22 31 | 
             
                    if !prop_string.start_with?("{") || !prop_string.end_with?("}")
         | 
| 23 32 | 
             
                      raise StandardError.new "Props statement: expecting hash as parameter"
         | 
| @@ -31,9 +40,9 @@ module RBlade | |
| 31 40 |  | 
| 32 41 | 
             
                      key, value = prop.split(/^
         | 
| 33 42 | 
             
                        (?:
         | 
| 34 | 
            -
                          ( | 
| 43 | 
            +
                          '(.+)':
         | 
| 35 44 | 
             
                          |
         | 
| 36 | 
            -
                          ( | 
| 45 | 
            +
                          "(.+)":
         | 
| 37 46 | 
             
                          |
         | 
| 38 47 | 
             
                          ([^ :]+):
         | 
| 39 48 | 
             
                          |
         | 
| @@ -56,6 +65,16 @@ module RBlade | |
| 56 65 |  | 
| 57 66 | 
             
                    props
         | 
| 58 67 | 
             
                  end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                  RUBY_RESERVED_KEYWORDS = %w[__FILE__ __LINE__ alias and begin BEGIN break case class def defined? do else elsif end END ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield].freeze
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  def isValidVariableName key
         | 
| 72 | 
            +
                    return false unless key.match?(/^[a-zA-Z_][a-zA-Z0-9_]*$/)
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                    return false if RUBY_RESERVED_KEYWORDS.include? key
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                    true
         | 
| 77 | 
            +
                  end
         | 
| 59 78 | 
             
                end
         | 
| 60 79 | 
             
              end
         | 
| 61 80 | 
             
            end
         | 
| @@ -14,17 +14,13 @@ module RBlade | |
| 14 14 | 
             
                  end
         | 
| 15 15 |  | 
| 16 16 | 
             
                  def compilePrepend args
         | 
| 17 | 
            -
                    if args | 
| 18 | 
            -
                      raise StandardError.new "Prepend statement: wrong number of arguments (given #{args&.count}, expecting 1 | 
| 17 | 
            +
                    if args&.count != 1
         | 
| 18 | 
            +
                      raise StandardError.new "Prepend statement: wrong number of arguments (given #{args&.count}, expecting 1)"
         | 
| 19 19 | 
             
                    end
         | 
| 20 20 |  | 
| 21 | 
            -
                     | 
| 22 | 
            -
                      "RBlade::StackManager.prepend(#{args[0]}, #{args[1]});"
         | 
| 23 | 
            -
                    else
         | 
| 24 | 
            -
                      @push_counter += 1
         | 
| 21 | 
            +
                    @push_counter += 1
         | 
| 25 22 |  | 
| 26 | 
            -
             | 
| 27 | 
            -
                    end
         | 
| 23 | 
            +
                    "_p_#{@push_counter}=#{args[0]};_p_#{@push_counter}_b=_out;_out='';"
         | 
| 28 24 | 
             
                  end
         | 
| 29 25 |  | 
| 30 26 | 
             
                  def compileEndPrepend args
         | 
| @@ -37,18 +33,38 @@ module RBlade | |
| 37 33 | 
             
                    "RBlade::StackManager.prepend(_p_#{@push_counter + 1}, _out);_out=_p_#{@push_counter + 1}_b;"
         | 
| 38 34 | 
             
                  end
         | 
| 39 35 |  | 
| 36 | 
            +
                  def compilePrependIf args
         | 
| 37 | 
            +
                    if args&.count != 2
         | 
| 38 | 
            +
                      raise StandardError.new "Prepend if statement: wrong number of arguments (given #{args&.count}, expecting 2)"
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    "if #{args[0]};" + compilePrepend([args[1]])
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def compileEndPrependIf args
         | 
| 45 | 
            +
                    if !args.nil?
         | 
| 46 | 
            +
                      raise StandardError.new "End push if statement: wrong number of arguments (given #{args&.count}, expecting 0)"
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    "end;" + compileEndPush(nil)
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 40 52 | 
             
                  def compilePush args
         | 
| 41 | 
            -
                    if args | 
| 42 | 
            -
                      raise StandardError.new "Push statement: wrong number of arguments (given #{args&.count}, expecting 1 | 
| 53 | 
            +
                    if args&.count != 1
         | 
| 54 | 
            +
                      raise StandardError.new "Push statement: wrong number of arguments (given #{args&.count}, expecting 1)"
         | 
| 43 55 | 
             
                    end
         | 
| 44 56 |  | 
| 45 | 
            -
                     | 
| 46 | 
            -
                      "RBlade::StackManager.push(#{args[0]}, #{args[1]});"
         | 
| 47 | 
            -
                    else
         | 
| 48 | 
            -
                      @push_counter += 1
         | 
| 57 | 
            +
                    @push_counter += 1
         | 
| 49 58 |  | 
| 50 | 
            -
             | 
| 59 | 
            +
                    "_p_#{@push_counter}=#{args[0]};_p_#{@push_counter}_b=_out;_out='';"
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  def compilePushIf args
         | 
| 63 | 
            +
                    if args&.count != 2
         | 
| 64 | 
            +
                      raise StandardError.new "Push if statement: wrong number of arguments (given #{args&.count}, expecting 2)"
         | 
| 51 65 | 
             
                    end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    "if #{args[0]};" + compilePush([args[1]])
         | 
| 52 68 | 
             
                  end
         | 
| 53 69 |  | 
| 54 70 | 
             
                  def compileEndPush args
         | 
| @@ -60,6 +76,14 @@ module RBlade | |
| 60 76 |  | 
| 61 77 | 
             
                    "RBlade::StackManager.push(_p_#{@push_counter + 1}, _out);_out=_p_#{@push_counter + 1}_b;"
         | 
| 62 78 | 
             
                  end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  def compileEndPushIf args
         | 
| 81 | 
            +
                    if !args.nil?
         | 
| 82 | 
            +
                      raise StandardError.new "End push if statement: wrong number of arguments (given #{args&.count}, expecting 0)"
         | 
| 83 | 
            +
                    end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                    "end;" + compileEndPush(nil)
         | 
| 86 | 
            +
                  end
         | 
| 63 87 | 
             
                end
         | 
| 64 88 | 
             
              end
         | 
| 65 89 | 
             
            end
         | 
| @@ -12,12 +12,12 @@ module RBlade | |
| 12 12 | 
             
                      (?:
         | 
| 13 13 | 
             
                        (?:
         | 
| 14 14 | 
             
                          (@@)
         | 
| 15 | 
            -
                          (\w+(?!\w))
         | 
| 15 | 
            +
                          (\w+(?!\w)[!\?]?)
         | 
| 16 16 | 
             
                        )
         | 
| 17 17 | 
             
                        |
         | 
| 18 18 | 
             
                        (?:
         | 
| 19 19 | 
             
                          (@)
         | 
| 20 | 
            -
                          (\w+(?!\w))
         | 
| 20 | 
            +
                          (\w+(?!\w)[!\?]?)
         | 
| 21 21 | 
             
                          (?:[ \t]*
         | 
| 22 22 | 
             
                            (\(.*?\))
         | 
| 23 23 | 
             
                          )?
         | 
| @@ -45,6 +45,7 @@ module RBlade | |
| 45 45 | 
             
                      i += 1
         | 
| 46 46 | 
             
                    elsif segment == "@"
         | 
| 47 47 | 
             
                      tokenizeStatement! segments, i
         | 
| 48 | 
            +
                      handleSpecialCases! segments, i
         | 
| 48 49 |  | 
| 49 50 | 
             
                      i += 1
         | 
| 50 51 | 
             
                    elsif !segments[i].nil? && segments[i] != ""
         | 
| @@ -74,6 +75,16 @@ module RBlade | |
| 74 75 | 
             
                  segments[i] = Token.new(type: :statement, value: statement_data)
         | 
| 75 76 | 
             
                end
         | 
| 76 77 |  | 
| 78 | 
            +
                def handleSpecialCases!(segments, i)
         | 
| 79 | 
            +
                  case segments[i][:value][:name]
         | 
| 80 | 
            +
                  when "case"
         | 
| 81 | 
            +
                    # Remove any whitespace before a when statement
         | 
| 82 | 
            +
                    until segments[i + 1].nil? || segments[i + 1] == '@'
         | 
| 83 | 
            +
                      segments.delete_at i + 1
         | 
| 84 | 
            +
                    end
         | 
| 85 | 
            +
                  end
         | 
| 86 | 
            +
                end
         | 
| 87 | 
            +
             | 
| 77 88 | 
             
                def tokenizeArguments!(segments, segment_index)
         | 
| 78 89 | 
             
                  success = expandSegmentToEndParenthesis! segments, segment_index
         | 
| 79 90 |  | 
    
        data/lib/rblade/compiler.rb
    CHANGED
    
    | @@ -6,6 +6,7 @@ require "rblade/compiler/compiles_verbatim" | |
| 6 6 | 
             
            require "rblade/compiler/compiles_statements"
         | 
| 7 7 | 
             
            require "rblade/compiler/tokenizes_components"
         | 
| 8 8 | 
             
            require "rblade/compiler/tokenizes_statements"
         | 
| 9 | 
            +
            require "rblade/helpers/html_string"
         | 
| 9 10 |  | 
| 10 11 | 
             
            Token = Struct.new(:type, :value)
         | 
| 11 12 |  | 
| @@ -19,6 +20,14 @@ module RBlade | |
| 19 20 | 
             
                string.gsub(/['\\\x0]/, '\\\\\0')
         | 
| 20 21 | 
             
              end
         | 
| 21 22 |  | 
| 23 | 
            +
              def self.e string
         | 
| 24 | 
            +
                if string.is_a? HtmlString
         | 
| 25 | 
            +
                  string
         | 
| 26 | 
            +
                else
         | 
| 27 | 
            +
                  h(string)
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 22 31 | 
             
              class Compiler
         | 
| 23 32 | 
             
                def self.compileString(string_template)
         | 
| 24 33 | 
             
                  tokens = [Token.new(:unprocessed, string_template)]
         | 
| @@ -81,7 +81,7 @@ module RBlade | |
| 81 81 | 
             
                  compiled_component = RBlade::Compiler.compileString(code)
         | 
| 82 82 |  | 
| 83 83 | 
             
                  @@component_definitions \
         | 
| 84 | 
            -
                    << "def #{@@component_method_names[name]}(slot,attributes);_out='';" \
         | 
| 84 | 
            +
                    << "def #{@@component_method_names[name]}(slot,attributes,params,session,flash,cookies);_out='';" \
         | 
| 85 85 | 
             
                    << "_stacks=[];" \
         | 
| 86 86 | 
             
                    << "attributes=RBlade::AttributesManager.new(attributes);" \
         | 
| 87 87 | 
             
                    << compiled_component \
         | 
| @@ -1,5 +1,7 @@ | |
| 1 | 
            +
            require "rblade/helpers/html_string"
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module RBlade
         | 
| 2 | 
            -
              class AttributesManager
         | 
| 4 | 
            +
              class AttributesManager < HtmlString
         | 
| 3 5 | 
             
                @attributes = {}
         | 
| 4 6 | 
             
                def initialize attributes
         | 
| 5 7 | 
             
                  @attributes = attributes
         | 
| @@ -17,12 +19,16 @@ module RBlade | |
| 17 19 | 
             
                  !@attributes[key].nil?
         | 
| 18 20 | 
             
                end
         | 
| 19 21 |  | 
| 20 | 
            -
                def method_missing(method,  | 
| 21 | 
            -
                   | 
| 22 | 
            +
                def method_missing(method, *, &block)
         | 
| 23 | 
            +
                  if [:select, :filter, :slice].include? method
         | 
| 24 | 
            +
                    AttributesManager.new @attributes.send(method, *, &block)
         | 
| 25 | 
            +
                  else
         | 
| 26 | 
            +
                    @attributes.send(method, *, &block)
         | 
| 27 | 
            +
                  end
         | 
| 22 28 | 
             
                end
         | 
| 23 29 |  | 
| 24 30 | 
             
                def respond_to_missing?(method_name, *args)
         | 
| 25 | 
            -
                  @attributes.respond_to?(method_name) | 
| 31 | 
            +
                  @attributes.respond_to?(method_name)
         | 
| 26 32 | 
             
                end
         | 
| 27 33 |  | 
| 28 34 | 
             
                def to_s attributes = nil
         | 
| @@ -33,6 +39,10 @@ module RBlade | |
| 33 39 | 
             
                  end.join " "
         | 
| 34 40 | 
             
                end
         | 
| 35 41 |  | 
| 42 | 
            +
                def to_str
         | 
| 43 | 
            +
                  to_s
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 36 46 | 
             
                def only(keys)
         | 
| 37 47 | 
             
                  keys = if keys.is_a? Array
         | 
| 38 48 | 
             
                    keys.map(&:to_sym)
         | 
| @@ -40,7 +50,7 @@ module RBlade | |
| 40 50 | 
             
                    [keys.to_sym]
         | 
| 41 51 | 
             
                  end
         | 
| 42 52 |  | 
| 43 | 
            -
                   | 
| 53 | 
            +
                  AttributesManager.new @attributes.slice(*keys)
         | 
| 44 54 | 
             
                end
         | 
| 45 55 |  | 
| 46 56 | 
             
                def except(keys)
         | 
| @@ -50,7 +60,15 @@ module RBlade | |
| 50 60 | 
             
                    [keys.to_sym]
         | 
| 51 61 | 
             
                  end
         | 
| 52 62 |  | 
| 53 | 
            -
                   | 
| 63 | 
            +
                  AttributesManager.new @attributes.except(*keys)
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                def class(new_classes)
         | 
| 67 | 
            +
                  new_classes = ClassManager.new(new_classes).to_s
         | 
| 68 | 
            +
                  attributes = @attributes.dup
         | 
| 69 | 
            +
                  attributes[:class] = mergeClasses attributes[:class], new_classes
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  AttributesManager.new attributes
         | 
| 54 72 | 
             
                end
         | 
| 55 73 |  | 
| 56 74 | 
             
                def merge(default_attributes)
         | 
| @@ -70,7 +88,19 @@ module RBlade | |
| 70 88 | 
             
                    new_attributes[key] = value
         | 
| 71 89 | 
             
                  end
         | 
| 72 90 |  | 
| 73 | 
            -
                   | 
| 91 | 
            +
                  AttributesManager.new new_attributes
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                def has?(*keys)
         | 
| 95 | 
            +
                  keys.map!(&:to_sym)
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  keys.all? { |key| @attributes.has_key? key }
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                def has_any?(*keys)
         | 
| 101 | 
            +
                  keys.map!(&:to_sym)
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                  keys.any? { |key| @attributes.has_key? key }
         | 
| 74 104 | 
             
                end
         | 
| 75 105 |  | 
| 76 106 | 
             
                private
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            require "rblade/helpers/attributes_manager"
         | 
| 2 | 
            +
            require "rblade/helpers/html_string"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module RBlade
         | 
| 5 | 
            +
              class SlotManager < HtmlString
         | 
| 6 | 
            +
                def initialize content, attributes = nil
         | 
| 7 | 
            +
                  @content = content
         | 
| 8 | 
            +
                  @attributes = attributes && AttributesManager.new(attributes)
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def to_s
         | 
| 12 | 
            +
                  @content
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def to_str
         | 
| 16 | 
            +
                  to_s
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def method_missing(method, *)
         | 
| 20 | 
            +
                  @content.send(method, *)
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def respond_to_missing?(method_name, *args)
         | 
| 24 | 
            +
                  @content.respond_to?(method_name)
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def attributes
         | 
| 28 | 
            +
                  @attributes
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
| @@ -3,6 +3,7 @@ require "rblade/compiler" | |
| 3 3 | 
             
            require "rblade/component_store"
         | 
| 4 4 | 
             
            require "rblade/helpers/attributes_manager"
         | 
| 5 5 | 
             
            require "rblade/helpers/class_manager"
         | 
| 6 | 
            +
            require "rblade/helpers/slot_manager"
         | 
| 6 7 | 
             
            require "rblade/helpers/stack_manager"
         | 
| 7 8 | 
             
            require "rblade/helpers/style_manager"
         | 
| 8 9 |  | 
    
        data/rblade.gemspec
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            Gem::Specification.new do |s|
         | 
| 2 2 | 
             
              s.name = "rblade"
         | 
| 3 | 
            -
              s.version = "0. | 
| 3 | 
            +
              s.version = "0.6.1"
         | 
| 4 4 | 
             
              s.summary = "A component-first templating engine for Rails"
         | 
| 5 5 | 
             
              s.description = "RBlade is a simple, yet powerful templating engine for Ruby on Rails, inspired by Laravel Blade."
         | 
| 6 6 | 
             
              s.authors = ["Simon J"]
         |