rblade 1.0.5 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +7 -0
- data/README.md +22 -6
- data/REFERENCE.md +19 -15
- data/lib/rblade/compiler/compiles_statements.rb +2 -0
- data/lib/rblade/compiler/statements/compiles_component_helpers.rb +3 -3
- data/lib/rblade/compiler/statements/compiles_loops.rb +56 -9
- data/lib/rblade/helpers/attributes_manager.rb +1 -1
- data/rblade.gemspec +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 12abc58f2de63aabc65abf34fe60b17b63b8ba70141dbd16447d6d5b42b84a0a
|
4
|
+
data.tar.gz: 101e136868a7cbb2d5eb7ab2d117b90013999c1dcd544726fa9a0423a3b6566e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a96e14502ccb338afc0779779f8d18901b9f8ea4ef90ba26e0142d24acc7f8a8cac85e290f3109a92b7d82c5752da795481084c733810dc3ffcfed97302a6c4
|
7
|
+
data.tar.gz: 0a17982fdb228fb5edaa308e9dbb2c58a16c9733d2bd5bbe89188a4bb1431940558be5904a41d02093fe9ae5346b631a98bcd2dd825fe72e47de390e85912343
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## 1.1.1 [2024-08-23]
|
2
|
+
- Remove requirement for including braces in `@props` directive
|
3
|
+
|
4
|
+
## 1.1.0 [2024-08-23]
|
5
|
+
- Add `@eachWithIndex` directive
|
6
|
+
- Fix attribute manager output of attributes with no value (#10)
|
7
|
+
|
1
8
|
## 1.0.5 [2024-08-14]
|
2
9
|
- Allow use of variables in @method directive
|
3
10
|
|
data/README.md
CHANGED
@@ -222,6 +222,16 @@ In addition to conditional statements, RBlade provides simple directives for wor
|
|
222
222
|
<p>This is user {{ user.id }}</p>
|
223
223
|
@endEach
|
224
224
|
|
225
|
+
{{-- Compiles to users.each_with_index do |user, index| ... --}}
|
226
|
+
@eachWithIndex (user, index in users)
|
227
|
+
<p>This is user {{ index }} {{ user.name }}</p>
|
228
|
+
@endEachWithIndex
|
229
|
+
|
230
|
+
{{-- eachWithIndex has a special case for Hashes: in this example, the result is "Item 1: a A" --}}
|
231
|
+
@eachWithIndex (key, value, index in {a: 'A'})
|
232
|
+
Item #{{ index + 1 }}: {{ key }} {{ value }}
|
233
|
+
@endEachWithIndex
|
234
|
+
|
225
235
|
@forElse (name in [])
|
226
236
|
<li>{{ name }}</li>
|
227
237
|
@empty
|
@@ -234,6 +244,12 @@ In addition to conditional statements, RBlade provides simple directives for wor
|
|
234
244
|
<p>No users</p>
|
235
245
|
@endEachElse
|
236
246
|
|
247
|
+
@eachWithIndexElse (user, index in users)
|
248
|
+
<li>{{ index }}: {{ user.name }}</li>
|
249
|
+
@empty
|
250
|
+
<p>No users</p>
|
251
|
+
@endEachWithIndexElse
|
252
|
+
|
237
253
|
@while (true)
|
238
254
|
<p>I'm looping forever.</p>
|
239
255
|
@endWhile
|
@@ -475,7 +491,7 @@ You can define a component's data properties using a `@props` directive at the t
|
|
475
491
|
|
476
492
|
```rblade
|
477
493
|
{{-- alert.rblade --}}
|
478
|
-
@props(
|
494
|
+
@props(type: "warning", message: required)
|
479
495
|
<div class="{{ type }}">{{ message }}</div>
|
480
496
|
```
|
481
497
|
|
@@ -489,7 +505,7 @@ The `@props` directive accepts a Hash where the key is the name of the attribute
|
|
489
505
|
All properties in the `@props` directive are automatically removed from `attributes`. Properties with names that aren't valid Ruby variable names or are Ruby reserved keywords are not created as local variables. However, you can reference them via the `attributes` local variable:
|
490
506
|
|
491
507
|
```rblade
|
492
|
-
@props(
|
508
|
+
@props("for": required, "data-value": nil)
|
493
509
|
<div>{{ attributes[:for] }} {{ attributes[:'data-value'] }}</div>
|
494
510
|
```
|
495
511
|
|
@@ -681,7 +697,7 @@ Sometimes a component may need to render multiple different slots in different l
|
|
681
697
|
|
682
698
|
```rblade
|
683
699
|
{{-- /app/views/components/alert.rblade --}}
|
684
|
-
@props(
|
700
|
+
@props(title: required)
|
685
701
|
<span class="alert-title">{{ title }}</span>
|
686
702
|
<div class="alert alert-danger">
|
687
703
|
{{ slot }}
|
@@ -736,10 +752,10 @@ Like RBlade components, you can assign additional [attributes](#component-attrib
|
|
736
752
|
To interact with slot attributes, you can access the `attributes` property of the slot's variable. For more information on how to interact with attributes, please consult the documentation on [component attributes](#component-attributes):
|
737
753
|
|
738
754
|
```rblade
|
739
|
-
@props(
|
755
|
+
@props(
|
740
756
|
"heading": required,
|
741
757
|
"footer": required,
|
742
|
-
|
758
|
+
)
|
743
759
|
|
744
760
|
<div {{ attributes.class('border') }}>
|
745
761
|
<h1 {{ heading.attributes.class('text-lg') }}>
|
@@ -761,7 +777,7 @@ Sometimes, you may wish to return early from a component without printing anythi
|
|
761
777
|
|
762
778
|
```rblade
|
763
779
|
{{-- components/error.rblade --}}
|
764
|
-
@props(
|
780
|
+
@props(errors: [])
|
765
781
|
@shouldRender(errors.present?)
|
766
782
|
...
|
767
783
|
```
|
data/REFERENCE.md
CHANGED
@@ -30,12 +30,13 @@ By default, RBlade will look for components in the `app/views/components` folder
|
|
30
30
|
| `<x-name @style({'bg-red-600': is_error})/>` | Conditionally pass styles to a component |
|
31
31
|
| `<x-name attribute/>` | Pass an attribute to a component with value `true` |
|
32
32
|
| `<x-name {{ attributes }}/>` | Pass attributes to a child component |
|
33
|
-
| `@props(
|
34
|
-
| `@props(
|
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
35
|
| `{{ slot }}` | Output the block content passed into the current component |
|
36
36
|
| `<x-name><x-slot::header><h1>Header</h1><//>Content<//>` | Pass a named block to a component |
|
37
37
|
| `{{ header }}` | Output the contents of a named block |
|
38
38
|
| `<div {{ header.attributes }}>` | Output the attributes passed into a named block |
|
39
|
+
| `@shouldRender(RUBY_EXPRESSION)` | Only renders the component if RUBY_EXPRESSION evaluates to true |
|
39
40
|
|
40
41
|
<a name="quick-reference-attributes"></a>
|
41
42
|
## Attributes
|
@@ -75,19 +76,22 @@ The attributes variable is an instance of a class that manages attributes. As we
|
|
75
76
|
<a name="quick-reference-loops"></a>
|
76
77
|
## Loops
|
77
78
|
|
78
|
-
| Syntax
|
79
|
-
|
80
|
-
| `@while( looping ) ... @endWhile`
|
81
|
-
| `@until( finished ) ... @endUntil`
|
82
|
-
| `@for( i in 1..10 ) ... @endFor`
|
83
|
-
| `@each( i in 1..10 ) ... @endEach`
|
84
|
-
| `@each( key, value in {a: 1} ) ... @endEach`
|
85
|
-
| `@
|
86
|
-
| `@
|
87
|
-
| `@
|
88
|
-
| `@
|
89
|
-
| `@
|
90
|
-
| `@
|
79
|
+
| Syntax | Description |
|
80
|
+
|:-----------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------|
|
81
|
+
| `@while( looping ) ... @endWhile` | Compiles to a Ruby while statement |
|
82
|
+
| `@until( finished ) ... @endUntil` | Compiles to a Ruby until statement |
|
83
|
+
| `@for( i in 1..10 ) ... @endFor` | Compiles to a Ruby for loop |
|
84
|
+
| `@each( i in 1..10 ) ... @endEach` | Calls `each` on the given collection, with `\|i\|` as the block argument |
|
85
|
+
| `@each( key, value in {a: 1} ) ... @endEach` | Calls `each` on the given Hash, with `\|key, value\|` as the block arguments |
|
86
|
+
| `@eachWithIndex( value, index in ['a', 'b'] ) ... @endEachWithIndex` | Calls `each_with_index` on the given Array, with `\|value, index\|` as the block arguments |
|
87
|
+
| `@eachWithIndex( key, value, index in {a: 1} ) ... @endEachWithIndex` | Calls `each_with_index` on the given Hash, where `key` is the Hash key, `value` is the Hash value, and `index` is the index |
|
88
|
+
| `@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 |
|
89
|
+
| `@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 |
|
90
|
+
| `@eachWithIndexElse( value, index in 1..10 ) ... @empty ... @endEachWithIndexElse` | Compiles to a each_with_index loop as above, but the block after `@empty` is printed if the given collection is empty |
|
91
|
+
| `@break` | Break out of the current loop |
|
92
|
+
| `@next` | Go to the next iteration in the current loop |
|
93
|
+
| `@break( RUBY_EXPRESSION )` | Break out of the current loop if the expression evaluate to true |
|
94
|
+
| `@next( RUBY_EXPRESSION )` | Go to the next iteration in the current loop if the expression evaluate to true |
|
91
95
|
|
92
96
|
<a name="quick-reference-forms"></a>
|
93
97
|
## Forms
|
@@ -81,6 +81,8 @@ module RBlade
|
|
81
81
|
"elsif" => [CompilesConditionals, :compileElsif],
|
82
82
|
"each" => [CompilesLoops, :compileEach],
|
83
83
|
"eachelse" => [CompilesLoops, :compileEachElse],
|
84
|
+
"eachwithindex" => [CompilesLoops, :compileEachWithIndex],
|
85
|
+
"eachwithindexelse" => [CompilesLoops, :compileEachWithIndexElse],
|
84
86
|
"empty" => [CompilesLoops, :compileEmpty],
|
85
87
|
"empty?" => [CompilesConditionals, :compileEmpty],
|
86
88
|
"end" => [CompilesStatements, :compileEnd],
|
@@ -42,12 +42,12 @@ module RBlade
|
|
42
42
|
private
|
43
43
|
|
44
44
|
def extractProps prop_string
|
45
|
-
if
|
46
|
-
|
45
|
+
if prop_string.start_with?("{") && prop_string.end_with?("}")
|
46
|
+
prop_string = prop_string.delete_prefix("{").delete_suffix("}")
|
47
47
|
end
|
48
48
|
|
49
49
|
props = {}
|
50
|
-
prop_strings = Tokenizer.extractCommaSeparatedValues prop_string
|
50
|
+
prop_strings = Tokenizer.extractCommaSeparatedValues prop_string
|
51
51
|
|
52
52
|
prop_strings.each do |prop|
|
53
53
|
prop.strip!
|
@@ -19,27 +19,74 @@ module RBlade
|
|
19
19
|
|
20
20
|
def compileEach args
|
21
21
|
if args.nil? || args.count > 2
|
22
|
-
raise StandardError.new "Each statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
|
22
|
+
raise StandardError.new "Each statement: wrong number of arguments (given #{args&.count || 0}, expecting 1 or 2)"
|
23
23
|
end
|
24
|
-
|
25
|
-
args
|
24
|
+
last_arg, collection = args.pop.split(" in ")
|
25
|
+
args.push(last_arg)
|
26
26
|
|
27
|
-
|
27
|
+
if collection.nil?
|
28
|
+
raise StandardError.new "Each statement: collection not found (expecting 'in')"
|
29
|
+
end
|
28
30
|
|
29
|
-
"#{collection}.each do |#{
|
31
|
+
"#{collection}.each do |#{args.join(",")}|;"
|
32
|
+
end
|
33
|
+
|
34
|
+
def compileEachWithIndex args
|
35
|
+
if args.nil? || args.count > 3
|
36
|
+
raise StandardError.new "Each with index statement: wrong number of arguments (given #{args&.count || 0}, expecting 1 to 3)"
|
37
|
+
end
|
38
|
+
last_arg, collection = args.pop.split(" in ")
|
39
|
+
args.push(last_arg)
|
40
|
+
|
41
|
+
if collection.nil?
|
42
|
+
raise StandardError.new "Each with index statement: collection not found (expecting 'in')"
|
43
|
+
end
|
44
|
+
|
45
|
+
# Special case for 3 arguments: the first 2 arguments are the key/value pair in a Hash, and
|
46
|
+
# the third is the index
|
47
|
+
if args.count == 3
|
48
|
+
"#{collection}.each_with_index do |_ivar,#{args[2]}|;#{args[0]},#{args[1]}=_ivar;"
|
49
|
+
else
|
50
|
+
"#{collection}.each_with_index do |#{args.join(",")}|;"
|
51
|
+
end
|
30
52
|
end
|
31
53
|
|
32
54
|
def compileEachElse args
|
33
55
|
if args.nil? || args.count > 2
|
34
56
|
raise StandardError.new "Each else statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
|
35
57
|
end
|
36
|
-
|
37
|
-
args
|
58
|
+
last_arg, collection = args.pop.split(" in ")
|
59
|
+
args.push(last_arg)
|
60
|
+
|
61
|
+
if collection.nil?
|
62
|
+
raise StandardError.new "Each else statement: collection not found (expecting 'in')"
|
63
|
+
end
|
64
|
+
|
38
65
|
@loop_else_counter += 1
|
39
66
|
|
40
|
-
|
67
|
+
"_looped_#{@loop_else_counter}=false;#{collection}.each do |#{args.join(",")}|;_looped_#{@loop_else_counter}=true;"
|
68
|
+
end
|
69
|
+
|
70
|
+
def compileEachWithIndexElse args
|
71
|
+
if args.nil? || args.count > 3
|
72
|
+
raise StandardError.new "Each with index statement: wrong number of arguments (given #{args&.count || 0}, expecting 1 to 3)"
|
73
|
+
end
|
74
|
+
last_arg, collection = args.pop.split(" in ")
|
75
|
+
args.push(last_arg)
|
76
|
+
|
77
|
+
if collection.nil?
|
78
|
+
raise StandardError.new "Each with index statement: collection not found (expecting 'in')"
|
79
|
+
end
|
80
|
+
|
81
|
+
@loop_else_counter += 1
|
41
82
|
|
42
|
-
|
83
|
+
# Special case for 3 arguments: the first 2 arguments are the key/value pair in a Hash, and
|
84
|
+
# the third is the index
|
85
|
+
if args.count == 3
|
86
|
+
"_looped_#{@loop_else_counter}=false;#{collection}.each_with_index do |_ivar,#{args[2]}|;#{args[0]},#{args[1]}=_ivar;_looped_#{@loop_else_counter}=true;"
|
87
|
+
else
|
88
|
+
"_looped_#{@loop_else_counter}=false;#{collection}.each_with_index do |#{args.join(",")}|;_looped_#{@loop_else_counter}=true;"
|
89
|
+
end
|
43
90
|
end
|
44
91
|
|
45
92
|
def compileFor args
|
data/rblade.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "rblade"
|
3
|
-
s.version = "1.
|
3
|
+
s.version = "1.1.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"]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rblade
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simon J
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-08-
|
11
|
+
date: 2024-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -140,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
140
|
- !ruby/object:Gem::Version
|
141
141
|
version: '0'
|
142
142
|
requirements: []
|
143
|
-
rubygems_version: 3.
|
143
|
+
rubygems_version: 3.3.5
|
144
144
|
signing_key:
|
145
145
|
specification_version: 4
|
146
146
|
summary: A component-first templating engine for Rails
|