rblade 0.5.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/REFERENCE.md ADDED
@@ -0,0 +1,138 @@
1
+ <a name="quick-reference"></a>
2
+ # Quick Reference
3
+
4
+ A table below provides a quick overview of RBlade syntax and directives. The [readme](README.md) has a more in depth look at RBlade's capabilities.
5
+
6
+ | Syntax | Description |
7
+ |:--------------------------------------------------------|:------------------------------------------------------------------------------------------|
8
+ | `{{ RUBY_EXPRESSION }}`<br/>`<%= RUBY_EXPRESSION %>` | Print the string value of the ruby expression, escaping HTML special characters |
9
+ | `{!! RUBY_EXPRESSION !!}`<br/>`<%== RUBY_EXPRESSION %>` | Print the string value of the ruby expression, _without_ escaping HTML special characters |
10
+ | `@ruby( RUBY_EXPRESSION )` | Execute an inline ruby expression |
11
+ | `@ruby ... @endRuby` | Execute a block of ruby code |
12
+ | `{{-- ... --}}`<br/>`<%# ... %>` | Comments, removed from the compiled template with no performance cost |
13
+ | `@verbatim ... @endVerbatim` | Print the given content without parsing RBlade directives |
14
+
15
+ <a name="quick-reference-components"></a>
16
+ ## Components
17
+
18
+ By default, RBlade will look for components in the `app/views/components` folder. Additionally, components in the `layout` namespace are found in the `app/views/layouts` folder, and components in the `view` namespace are found in the `app/views` folder.
19
+
20
+ | Syntax | Description |
21
+ |:---------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------|
22
+ | `<x-component.name/>` | Render the component found at `app/views/components/name{.rblade,.html.rblade}` or `app/views/components/name/index{.rblade,.html.rblade}` |
23
+ | `<x-layout::name/>` | Render the "name" component found in the "layout" namespace folder |
24
+ | `<x-component.name>...</x-component.name>` | Render the component with the given slot content |
25
+ | `<x-component.name>...<//>` | Short closing tag syntax (note: this bypasses some sanity checking during compilation) |
26
+ | `<x-name attribute="STRING"/>` | Pass a string value to a component |
27
+ | `<x-name :attribute="RUBY_EXPRESSION"/>` | Pass a ruby expression, executed in the local scope, to a component |
28
+ | `<x-name :attribute/>` | Pass the `attribute` local variable into a component |
29
+ | `<x-name @class({'bg-red-600': is_error})/>` | Conditionally pass classes to a component |
30
+ | `<x-name @style({'bg-red-600': is_error})/>` | Conditionally pass styles to a component |
31
+ | `<x-name attribute/>` | Pass an attribute to a component with value `true` |
32
+ | `<x-name {{ attributes }}/>` | Pass attributes to a child component |
33
+ | `@props({header: "Header"})` | Remove `header` from the attributes Hash and introduce it as a local variable, using the specified value as a default |
34
+ | `@props({header: _required})` | Remove `header` from the attributes Hash and introduce it as a local variable, raising an error if it is not set |
35
+ | `{{ slot }}` | Output the block content passed into the current component |
36
+ | `<x-name><x-slot::header><h1>Header</h1><//>Content<//>` | Pass a named block to a component |
37
+ | `{{ header }}` | Output the contents of a named block |
38
+ | `<div {{ header.attributes }}>` | Output the attributes passed into a named block |
39
+
40
+ <a name="quick-reference-attributes"></a>
41
+ ## Attributes
42
+
43
+ The attributes variable is an instance of a class that manages attributes. As well as the methods used in the examples below, you can use any method belonging to the Hash class.
44
+
45
+ | Syntax | Description |
46
+ |:-------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------|
47
+ | `<div {{ attributes }}>` | Print the contents of attributes as HTML attributes |
48
+ | `<div {{ attributes.merge({class: "text-black", type: "button"}) }}>` | Merge in additional attributes, combining the `:class` and `:style`, and setting defaults for other values |
49
+ | `<div {{ attributes.except(['type']) }}>` | Output the attributes array excluding the given keys |
50
+ | `<div {{ attributes.only(['type']) }}>` | Output only the given keys of the attributes array |
51
+ | `<div {{ attributes.filter { \|key, value\| key.start_with? "on:" } }}>` | Output the attributes for which the block returns true |
52
+ | `<div @class({'bg-red-600': is_error})>` | Conditionally print classes in an HTML class attribute |
53
+ | `<div @style({'bg-red-600': is_error})>` | Conditionally print styles in an HTML style attribute |
54
+
55
+ <a name="quick-reference-conditions"></a>
56
+ ## Conditions
57
+
58
+ | Syntax | Description |
59
+ |:----------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------|
60
+ | `@if( RUBY_EXPRESSION ) ... @endIf` | Compiles to a Ruby if statement |
61
+ | `@if( RUBY_EXPRESSION ) ... @else ... @endIf` | Compiles to a Ruby if/else statement |
62
+ | `@if( RUBY_EXPRESSION ) ... @elsif( RUBY_EXPRESSION ) ... @endIf` | Compiles to a Ruby if/elsif statement |
63
+ | `@unless( RUBY_EXPRESSION ) ... @endunless` | Compiles to a Ruby unless statement |
64
+ | `@case( RUBY_EXPRESSION ) @when(1) ... @when(2) ... @else ... @endIf` | Compiles to a Ruby case statement |
65
+ | `@blank?( RUBY_EXPRESSION ) ... @endBlank?` | Compiles to a Ruby if statement that calls `blank?` method on the given expression |
66
+ | `@defined?( RUBY_EXPRESSION ) ... @endDefined?` | Compiles to a Ruby if statement that calls `defined?` function on the given expression |
67
+ | `@empty?( RUBY_EXPRESSION ) ... @endEmpty?` | Compiles to a Ruby if statement that calls `empty?` method on the given expression |
68
+ | `@nil?( RUBY_EXPRESSION ) ... @endNil?` | Compiles to a Ruby if statement that calls `nil?` method on the given expression |
69
+ | `@present?( RUBY_EXPRESSION ) ... @endPresent?` | Compiles to a Ruby if statement that calls `present?` method on the given expression |
70
+ | `@env(['development', 'test']) ... @endEnv` | Compiles to a Ruby if statement that checks if the current Rails environment matches any of the given environments |
71
+ | `@production ... @endProduction` | Shortcut for `@env('production')` |
72
+ | `@once ... @endOnce` | Render the given block the first time it appears in the template |
73
+ | `@once('unique key') ... @endOnce` | Render the given block the first time "unique key" is used in the template |
74
+
75
+ <a name="quick-reference-loops"></a>
76
+ ## Loops
77
+
78
+ | Syntax | Description |
79
+ |:------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------|
80
+ | `@while( looping ) ... @endWhile` | Compiles to a Ruby while statement |
81
+ | `@until( finished ) ... @endUntil` | Compiles to a Ruby until statement |
82
+ | `@for( i in 1..10 ) ... @endFor` | Compiles to a Ruby for loop |
83
+ | `@each( i in 1..10 ) ... @endEach` | Calls `each` on the given collection, with `\|i\|` as the block argument |
84
+ | `@each( key, value in {a: 1} ) ... @endEach` | Calls `each` on the given Hash, with `\|key, value\|` as the block arguments |
85
+ | `@forElse( i in 1..10 ) ... @empty ... @endForElse` | Compiles to a for loop as above, but the block after `@empty` is printed if the given collection is empty |
86
+ | `@eachElse( i in 1..10 ) ... @empty ... @endEachElse` | Compiles to a each loop as above, but the block after `@empty` is printed if the given collection is empty |
87
+ | `@break` | Break out of the current loop |
88
+ | `@next` | Go to the next iteration in the current loop |
89
+ | `@break( RUBY_EXPRESSION )` | Break out of the current loop if the expression evaluate to true |
90
+ | `@next( RUBY_EXPRESSION )` | Go to the next iteration in the current loop if the expression evaluate to true |
91
+
92
+ <a name="quick-reference-forms"></a>
93
+ ## Forms
94
+
95
+ | Syntax | Description |
96
+ |:---------------------------------|:-----------------------------------------------------------------------------------------------------------------|
97
+ | `@old(:email, user[:email])` | Fetches `:email` from the params Hash, defaulting to the user's email if it doesn't exist |
98
+ | `@method('PATCH')` | Prints a hidden input setting the HTTP request type to the given value using the Rails MethodOverride middleware |
99
+ | `@DELETE` | Shortcut for `@method('DELETE')` |
100
+ | `@PATCH` | Shortcut for `@method('PATCH')` |
101
+ | `@PUT` | Shortcut for `@method('PUT')` |
102
+ | `@checked( RUBY_EXPRESSION )` | Prints "checked" if the ruby expression evaluates to true |
103
+ | `@disabled( RUBY_EXPRESSION )` | Prints "disabled" if the ruby expression evaluates to true |
104
+ | `@readonly( RUBY_EXPRESSION )` | Prints "readonly" if the ruby expression evaluates to true |
105
+ | `@required( RUBY_EXPRESSION )` | Prints "required" if the ruby expression evaluates to true |
106
+ | `@selected( RUBY_EXPRESSION )` | Prints "selected" if the ruby expression evaluates to true |
107
+
108
+ <a name="quick-reference-stacks"></a>
109
+ ## Stacks
110
+
111
+ Stacks are a way of rendering content outside of the usual document order. For example, you could define a "sidebar" stack, then you'd be able to add content to that sidebar from anywhere else in the site.
112
+
113
+ Note that the stack is printed once the current view or component finishes.
114
+
115
+ | Syntax | Description |
116
+ |:------------------------------------------------------------|:--------------------------------------------------------------------------------------------|
117
+ | `@stack('scripts')` | Start a stack with the name 'scripts'. Stacks can be pushed to elsewhere in the code. |
118
+ | `@push('scripts') ... @endPush` | Add block content to the 'scripts' stack |
119
+ | `@prepend('scripts') ... @endPrepend` | Add block content to the start of the 'scripts' stack |
120
+ | `@pushIf(RUBY_EXPRESSION, 'scripts') ... @endPushIf` | Add block content to the 'scripts' stack if the expression evaluate to true |
121
+ | `@prependIf(RUBY_EXPRESSION, 'scripts') ... @endprependIf` | Add block content to the start of the 'scripts' stack if the expression evaluate to true |
122
+ | `@pushOnce('scripts') ... @endPushOnce` | Add block content to the 'scripts' stack only once |
123
+ | `@prependOnce('scripts') ... @endPrependOnce` | Add block content to the start of the 'scripts' stack only once |
124
+ | `@pushOnce('scripts', 'unique key') ... @endPushOnce` | Add block content to the 'scripts' stack the first time "unique key" is pushed |
125
+ | `@prependOnce('scripts', 'unique key') ... @endPrependOnce` | Add block content to the start of the 'scripts' stack the first time "unique key" is pushed |
126
+
127
+ ## Tips
128
+
129
+ * Except for `@push`, `@prepend` and their variants, all end directives can simply be replaced with `@end` if preferred:
130
+ - `@nil?(...) ... @endnil?`
131
+ - `@nil?(...) ... @endnil`
132
+ - `@nil?(...) ... @end`
133
+ * Except for `@ruby` and `@verbatim`, directives are case insensitive and can contain underscores. The following are identical:
134
+ - `@pushonce`
135
+ - `@pushOnce`
136
+ - `@PushOnce`
137
+ - `@push_once`
138
+ - `@PUSHONCE`
@@ -0,0 +1,3 @@
1
+ # RBlade Examples
2
+
3
+ This folder is structured like a Rails `app/views` folder and contains some examples of RBlade templates.
@@ -0,0 +1,23 @@
1
+ @ruby
2
+ # Typically these values would be set in the controller
3
+ banner_image = 'banner.png'
4
+ alert = nil
5
+ @endruby
6
+ <x-layout::app title="Home page">
7
+ <x-content.alert :alert/>
8
+ <x-content.alert alert="This is an alert"/>
9
+ <x-h1 blue>Welcome to the home page!</x-h1>
10
+
11
+ <x-p class="mt-2">
12
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias amet architecto, at commodi consectetur ipsa itaque magni minus neque nostrum pariatur possimus recusandae sunt! Est explicabo praesentium quidem vero voluptatum!
13
+ </x-p>
14
+
15
+ @if (banner_image)
16
+ <x-content.hero class="mt-4">
17
+ <x-slot::heading class="text-blue-600">
18
+ Beatae placeat porro quibusdam repudiandae sunt?
19
+ </x-slot::heading>
20
+ Adipisci blanditiis, dolor dolorem, ea iste laudantium minima natus nesciunt nostrum odio perferendis praesentium quae, similique.
21
+ </x-content.hero>
22
+ @endif
23
+ </x-layout::app>
@@ -0,0 +1,6 @@
1
+ @props({alert: _required})
2
+ @shouldRender(alert.present?)
3
+ <p class="py-2 px-3 bg-amber-100 border border-amber-500">
4
+ @@alert
5
+ {{ alert }}
6
+ </p>
@@ -0,0 +1,14 @@
1
+ @props({heading: nil})
2
+ @pushOnce('scripts')
3
+ <script src="/js/hero.js"></script>
4
+ @endPushOnce
5
+ <div class="bg-blue-50 p-16">
6
+ <div class="max-w-96">
7
+ @if (heading)
8
+ <h2 {{ heading.attributes.merge({class: "text-lg font-bold"}) }}>
9
+ {{ heading }}
10
+ </h2>
11
+ @end
12
+ <p class="mt-4">{{ slot }}</p>
13
+ </div>
14
+ </div>
@@ -0,0 +1,6 @@
1
+ @props({blue: false})
2
+ <h1 {{ attributes.merge({
3
+ class: "text-xl font-bold #{blue ? 'text-blue-700' : 'text-black'}"
4
+ }) }}>
5
+ {{ slot }}
6
+ </h1>
@@ -0,0 +1,14 @@
1
+ <p {{ attributes.merge({
2
+ class: "
3
+ text-base font-normal
4
+ {{--
5
+ The tailwindcss-unimportant plugin works well with component design:
6
+ the "-:" prefix allows the consumer of the component to easily override
7
+ the component classes and extend the component.
8
+ See: https://www.npmjs.com/package/tailwindcss-unimportant
9
+ --}}
10
+ -:mt-1
11
+ "
12
+ }) }}>
13
+ {{ slot }}
14
+ </p>
@@ -0,0 +1,16 @@
1
+ @props({title: _required})
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
8
+ <title>{{ title }}</title>
9
+ <script src="https://cdn.tailwindcss.com"></script>
10
+ @stack('scripts')
11
+ </head>
12
+ <body>
13
+ <div {{ attributes.merge({class: "max-w-prose mt-8 mx-auto flex flex-col gap-4"}) }}>
14
+ {{ slot }}
15
+ </body>
16
+ </html>
@@ -51,11 +51,11 @@ module RBlade
51
51
 
52
52
  namespace = nil
53
53
  name = component[:name]
54
- if name.match '::'
54
+ if name.match? "::"
55
55
  namespace, name = component[:name].split("::")
56
56
  end
57
57
 
58
- code = if namespace == 'slot'
58
+ if namespace == "slot"
59
59
  compile_slot_end name, component
60
60
  else
61
61
  compile_component_end component
@@ -73,7 +73,7 @@ module RBlade
73
73
 
74
74
  def compile_component_end component
75
75
  code = "_slot=RBlade::SlotManager.new(_out);_out=_c#{component[:index]}_swap;"
76
- code << "_out<<#{ComponentStore.component(component[:name])}(_slot,_c#{component[:index]}_attr);"
76
+ code << "_out<<#{ComponentStore.component(component[:name])}(_slot,_c#{component[:index]}_attr,params,session,flash,cookies);"
77
77
  code << "_slot=nil;_c#{component[:index]}_swap=nil;_c#{component[:index]}_attr=nil;"
78
78
 
79
79
  code
@@ -1,22 +1,23 @@
1
1
  module RBlade
2
- class CompilesEchos
2
+ class CompilesPrints
3
3
  def compile!(tokens)
4
- compile_regular_echos!(tokens)
5
- compile_unsafe_echos!(tokens)
4
+ compile_unsafe_prints!(tokens)
5
+ compile_regular_prints!(tokens)
6
6
  end
7
7
 
8
8
  private
9
9
 
10
- def compile_regular_echos!(tokens)
11
- compile_echos! tokens, "{{", "}}", "RBlade.e"
12
- compile_echos! tokens, "<%=", "%>", "RBlade.e"
10
+ def compile_regular_prints!(tokens)
11
+ compile_prints! tokens, "{{", "}}", "RBlade.e"
12
+ compile_prints! tokens, "<%=", "%>", "RBlade.e"
13
13
  end
14
14
 
15
- def compile_unsafe_echos!(tokens)
16
- compile_echos! tokens, "{!!", "!!}"
15
+ def compile_unsafe_prints!(tokens)
16
+ compile_prints! tokens, "{!!", "!!}"
17
+ compile_prints! tokens, "<%==", "%>"
17
18
  end
18
19
 
19
- def compile_echos!(tokens, start_token, end_token, wrapper_function = nil)
20
+ def compile_prints!(tokens, start_token, end_token, wrapper_function = nil)
20
21
  tokens.map! do |token|
21
22
  next(token) if token.type != :unprocessed
22
23
 
@@ -41,7 +42,7 @@ module RBlade
41
42
  else
42
43
  "(" + segments[i] + ").to_s;"
43
44
  end
44
- segments[i] = Token.new(:echo, segment_value)
45
+ segments[i] = Token.new(:print, segment_value)
45
46
 
46
47
  i += 1
47
48
  elsif !segments[i].nil? && segments[i] != ""
@@ -38,7 +38,7 @@ module RBlade
38
38
  segments[i] << ";"
39
39
  end
40
40
 
41
- segments[i] = Token.new(type: :php, value: segments[i])
41
+ segments[i] = Token.new(type: :ruby, value: segments[i])
42
42
 
43
43
  i += 1
44
44
  elsif !segments[i].nil? && segments[i] != ""
@@ -1,9 +1,10 @@
1
+ require "rblade/compiler/statements/compiles_component_helpers"
1
2
  require "rblade/compiler/statements/compiles_conditionals"
3
+ require "rblade/compiler/statements/compiles_form"
2
4
  require "rblade/compiler/statements/compiles_html_attributes"
3
5
  require "rblade/compiler/statements/compiles_inline_ruby"
4
6
  require "rblade/compiler/statements/compiles_loops"
5
7
  require "rblade/compiler/statements/compiles_once"
6
- require "rblade/compiler/statements/compiles_props"
7
8
  require "rblade/compiler/statements/compiles_stacks"
8
9
 
9
10
  module RBlade
@@ -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
- raise StandardError.new "Unhandled statement: @#{name}"
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,51 +69,52 @@ module RBlade
63
69
  @@handler_instances = {}
64
70
 
65
71
  @@statement_handlers = {
72
+ "blank?" => [CompilesConditionals, :compileBlank],
66
73
  "break" => [CompilesLoops, :compileBreak],
67
- "breakif" => [CompilesLoops, :compileBreakIf],
68
74
  "case" => [CompilesConditionals, :compileCase],
69
75
  "checked" => [CompilesConditionals, :compileChecked],
70
76
  "class" => [CompilesHtmlAttributes, :compileClass],
77
+ "defined?" => [CompilesConditionals, :compileDefined],
78
+ "delete" => [CompilesForm, :compileDelete],
71
79
  "disabled" => [CompilesConditionals, :compileDisabled],
72
80
  "else" => [CompilesConditionals, :compileElse],
73
81
  "elsif" => [CompilesConditionals, :compileElsif],
74
82
  "each" => [CompilesLoops, :compileEach],
75
83
  "eachelse" => [CompilesLoops, :compileEachElse],
76
84
  "empty" => [CompilesLoops, :compileEmpty],
85
+ "empty?" => [CompilesConditionals, :compileEmpty],
77
86
  "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
87
  "endprepend" => [CompilesStacks, :compileEndPrepend],
88
+ "endprependif" => [CompilesStacks, :compileEndPrependIf],
87
89
  "endprependonce" => [CompilesOnce, :compileEndPrependOnce],
88
- "endproduction" => [CompilesStatements, :compileEnd],
89
90
  "endpush" => [CompilesStacks, :compileEndPush],
91
+ "endpushif" => [CompilesStacks, :compileEndPushIf],
90
92
  "endpushonce" => [CompilesOnce, :compileEndPushOnce],
91
- "endunless" => [CompilesStatements, :compileEnd],
92
- "enduntil" => [CompilesStatements, :compileEnd],
93
- "endwhile" => [CompilesStatements, :compileEnd],
94
93
  "env" => [CompilesConditionals, :compileEnv],
95
94
  "for" => [CompilesLoops, :compileFor],
96
95
  "forelse" => [CompilesLoops, :compileForElse],
97
96
  "if" => [CompilesConditionals, :compileIf],
97
+ "method" => [CompilesForm, :compileMethod],
98
98
  "next" => [CompilesLoops, :compileNext],
99
- "nextif" => [CompilesLoops, :compileNextIf],
99
+ "nil?" => [CompilesConditionals, :compileNil],
100
+ "old" => [CompilesForm, :compileOld],
100
101
  "once" => [CompilesOnce, :compileOnce],
102
+ "patch" => [CompilesForm, :compilePatch],
101
103
  "prepend" => [CompilesStacks, :compilePrepend],
104
+ "prependif" => [CompilesStacks, :compilePrependIf],
102
105
  "prependonce" => [CompilesOnce, :compilePrependOnce],
106
+ "present?" => [CompilesConditionals, :compilePresent],
103
107
  "production" => [CompilesConditionals, :compileProduction],
104
- "props" => [CompilesProps, :compileProps],
108
+ "props" => [CompilesComponentHelpers, :compileProps],
105
109
  "push" => [CompilesStacks, :compilePush],
110
+ "pushif" => [CompilesStacks, :compilePushIf],
106
111
  "pushonce" => [CompilesOnce, :compilePushOnce],
112
+ "put" => [CompilesForm, :compilePut],
107
113
  "readonly" => [CompilesConditionals, :compileReadonly],
108
114
  "required" => [CompilesConditionals, :compileRequired],
109
115
  "ruby" => [CompilesInlineRuby, :compile],
110
116
  "selected" => [CompilesConditionals, :compileSelected],
117
+ "shouldrender" => [CompilesComponentHelpers, :compileShouldRender],
111
118
  "stack" => [CompilesStacks, :compileStack],
112
119
  "style" => [CompilesHtmlAttributes, :compileStyle],
113
120
  "unless" => [CompilesConditionals, :compileUnless],
@@ -2,10 +2,18 @@ require "rblade/helpers/tokenizer"
2
2
 
3
3
  module RBlade
4
4
  class CompilesStatements
5
- class CompilesProps
5
+ class CompilesComponentHelpers
6
+ def compileShouldRender args
7
+ if args&.count != 1
8
+ raise StandardError.new "Should render statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
9
+ end
10
+
11
+ "unless(#{args[0]});return'';end;"
12
+ end
13
+
6
14
  def compileProps args
7
- if args.nil?
8
- raise StandardError.new "Props statement: wrong number of arguments (given #{args&.count}, expecting 1)"
15
+ if args&.count != 1
16
+ raise StandardError.new "Props statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
9
17
  end
10
18
 
11
19
  props = extractProps args[0]
@@ -13,8 +21,8 @@ module RBlade
13
21
  compiled_code = ""
14
22
  if value == "_required"
15
23
  compiled_code << "if !attributes.has?(:'#{RBlade.escape_quotes(key)}');raise \"Props statement: #{key} is not defined\";end;"
16
- end
17
- if isValidVariableName key
24
+ compiled_code << "#{key}=attributes[:'#{RBlade.escape_quotes(key)}'];attributes.delete :'#{RBlade.escape_quotes(key)}';"
25
+ elsif isValidVariableName key
18
26
  compiled_code << "#{key}=attributes[:'#{RBlade.escape_quotes(key)}'].nil? ? #{value} : attributes[:'#{RBlade.escape_quotes(key)}'];"
19
27
  compiled_code << "attributes.delete :'#{RBlade.escape_quotes(key)}';"
20
28
  else
@@ -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)"
@@ -18,8 +58,8 @@ module RBlade
18
58
  end
19
59
 
20
60
  def compileElse args
21
- if !args.nil?
22
- raise StandardError.new "Else statement: wrong number of arguments (given #{args&.count || 0}, expecting 0)"
61
+ unless args.nil?
62
+ raise StandardError.new "Else statement: wrong number of arguments (given #{args.count}, expecting 0)"
23
63
  end
24
64
 
25
65
  "else;"
@@ -42,8 +82,8 @@ module RBlade
42
82
  end
43
83
 
44
84
  def compileWhen args
45
- if args.nil? || args.count == 0
46
- raise StandardError.new "When statement: wrong number of arguments (given #{args&.count || 0}, expecting at least 1)"
85
+ if args.nil?
86
+ raise StandardError.new "When statement: wrong number of arguments (given 0, expecting at least 1)"
47
87
  end
48
88
 
49
89
  "when #{args.join ","};"
@@ -101,19 +141,11 @@ module RBlade
101
141
 
102
142
  def compileProduction args
103
143
  unless args.nil?
104
- raise StandardError.new "Production statement: wrong number of arguments (given #{args.count}, expecting 1)"
144
+ raise StandardError.new "Production statement: wrong number of arguments (given #{args.count}, expecting 0)"
105
145
  end
106
146
 
107
147
  "if Rails.env.production?;"
108
148
  end
109
-
110
- def compileOnce args
111
- if args&.count&.> 1
112
- raise StandardError.new "Production statement: wrong number of arguments (given #{args.count}, expecting 0 or 1)"
113
- end
114
-
115
- args[0].nil? ? "" : args[0]
116
- end
117
149
  end
118
150
  end
119
151
  end
@@ -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 "Method 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
+ unless args.nil?
15
+ raise StandardError.new "Delete statement: wrong number of arguments (given #{args.count}, expecting 0)"
16
+ end
17
+
18
+ compileMethod(["DELETE"])
19
+ end
20
+
21
+ def compilePatch args
22
+ unless args.nil?
23
+ raise StandardError.new "Patch statement: wrong number of arguments (given #{args.count}, expecting 0)"
24
+ end
25
+
26
+ compileMethod(["PATCH"])
27
+ end
28
+
29
+ def compilePut args
30
+ unless args.nil?
31
+ raise StandardError.new "Put 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 "Old statement: wrong number of arguments (given #{args&.count || 0}, expecting 1 or 2)"
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
@@ -7,7 +7,7 @@ module RBlade
7
7
 
8
8
  def compileBreak args
9
9
  if args&.count&.> 1
10
- raise StandardError.new "Break statement: wrong number of arguments (given #{args&.count}, expecting 0 or 1)"
10
+ raise StandardError.new "Break statement: wrong number of arguments (given #{args.count}, expecting 0 or 1)"
11
11
  end
12
12
 
13
13
  if args.nil?
@@ -31,7 +31,7 @@ module RBlade
31
31
 
32
32
  def compileEachElse args
33
33
  if args.nil? || args.count > 2
34
- raise StandardError.new "Each statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
34
+ raise StandardError.new "Each else statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
35
35
  end
36
36
  # Allow variables to be a key, value pair
37
37
  args = args.join ","
@@ -59,7 +59,11 @@ module RBlade
59
59
  "_looped_#{@loop_else_counter}=false;for #{args[0]};_looped_#{@loop_else_counter}=true;"
60
60
  end
61
61
 
62
- def compileEmpty
62
+ def compileEmpty args
63
+ unless args.nil?
64
+ raise StandardError.new "Empty statement: wrong number of arguments (given #{args.count}, expecting 0)"
65
+ end
66
+
63
67
  @loop_else_counter -= 1
64
68
 
65
69
  "end;if !_looped_#{@loop_else_counter + 1};"
@@ -67,7 +71,7 @@ module RBlade
67
71
 
68
72
  def compileNext args
69
73
  if args&.count&.> 1
70
- raise StandardError.new "For statement: wrong number of arguments (given #{args&.count || 0}, expecting 0 or 1)"
74
+ raise StandardError.new "Next statement: wrong number of arguments (given #{args.count}, expecting 0 or 1)"
71
75
  end
72
76
 
73
77
  if args.nil?