rblade 2.0.2 → 3.0.0
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/.rubocop.yml +24 -0
- data/CHANGELOG.md +11 -0
- data/README.md +83 -16
- data/REFERENCE.md +4 -2
- data/do +4 -4
- data/docker-compose.yml +4 -1
- data/lib/rblade/compiler/compiles_comments.rb +2 -2
- data/lib/rblade/compiler/compiles_components.rb +26 -5
- data/lib/rblade/compiler/compiles_injections.rb +81 -0
- data/lib/rblade/compiler/compiles_statements.rb +69 -64
- data/lib/rblade/compiler/compiles_verbatim.rb +1 -1
- data/lib/rblade/compiler/statements/compiles_component_helpers.rb +17 -13
- data/lib/rblade/compiler/statements/compiles_conditionals.rb +18 -18
- data/lib/rblade/compiler/statements/compiles_form.rb +8 -8
- data/lib/rblade/compiler/statements/compiles_html_attributes.rb +2 -2
- data/lib/rblade/compiler/statements/compiles_inline_ruby.rb +1 -1
- data/lib/rblade/compiler/statements/compiles_loops.rb +11 -11
- data/lib/rblade/compiler/statements/compiles_once.rb +3 -3
- data/lib/rblade/compiler/statements/compiles_stacks.rb +5 -5
- data/lib/rblade/compiler/tokenizes_components.rb +30 -31
- data/lib/rblade/compiler/tokenizes_statements.rb +29 -30
- data/lib/rblade/compiler.rb +20 -19
- data/lib/rblade/component_store.rb +20 -20
- data/lib/rblade/helpers/attributes_manager.rb +10 -9
- data/lib/rblade/helpers/class_manager.rb +1 -1
- data/lib/rblade/helpers/slot_manager.rb +2 -2
- data/lib/rblade/helpers/stack_manager.rb +3 -3
- data/lib/rblade/helpers/style_manager.rb +1 -1
- data/lib/rblade/helpers/tokenizer.rb +5 -5
- data/lib/rblade/rails_template.rb +9 -2
- data/lib/rblade/railtie.rb +34 -2
- data/rblade.gemspec +4 -1
- metadata +50 -8
- data/lib/rblade/compiler/compiles_prints.rb +0 -83
- data/lib/rblade/compiler/compiles_ruby.rb +0 -59
@@ -3,7 +3,7 @@
|
|
3
3
|
module RBlade
|
4
4
|
class CompilesStatements
|
5
5
|
class CompilesStacks
|
6
|
-
def
|
6
|
+
def compile_stack(args)
|
7
7
|
if args&.count != 1
|
8
8
|
raise RBladeTemplateError.new "Stack statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
|
9
9
|
end
|
@@ -11,7 +11,7 @@ module RBlade
|
|
11
11
|
"@_rblade_stack_manager.initialize_stack(#{args[0]}, @output_buffer);_stacks.push(#{args[0]});"
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def compile_prepend(args)
|
15
15
|
if args&.count != 1
|
16
16
|
raise RBladeTemplateError.new "Prepend statement: wrong number of arguments (given #{args&.count || 0}, expecting 1)"
|
17
17
|
end
|
@@ -19,7 +19,7 @@ module RBlade
|
|
19
19
|
"@_rblade_stack_manager.prepend(#{args[0]}, @output_buffer) do;"
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
22
|
+
def compile_prepend_if(args)
|
23
23
|
if args&.count != 2
|
24
24
|
raise RBladeTemplateError.new "Prepend if statement: wrong number of arguments (given #{args&.count}, expecting 2)"
|
25
25
|
end
|
@@ -27,7 +27,7 @@ module RBlade
|
|
27
27
|
"(#{args[0]}) && @_rblade_stack_manager.prepend(#{args[1]}, @output_buffer) do;"
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
30
|
+
def compile_push(args)
|
31
31
|
if args&.count != 1
|
32
32
|
raise RBladeTemplateError.new "Push statement: wrong number of arguments (given #{args&.count}, expecting 1)"
|
33
33
|
end
|
@@ -35,7 +35,7 @@ module RBlade
|
|
35
35
|
"@_rblade_stack_manager.push(#{args[0]}, @output_buffer) do;"
|
36
36
|
end
|
37
37
|
|
38
|
-
def
|
38
|
+
def compile_push_if(args)
|
39
39
|
if args&.count != 2
|
40
40
|
raise RBladeTemplateError.new "Push if statement: wrong number of arguments (given #{args&.count || 0}, expecting 2)"
|
41
41
|
end
|
@@ -8,7 +8,7 @@ module RBlade
|
|
8
8
|
tokens.map! do |token|
|
9
9
|
next(token) if token.type != :unprocessed
|
10
10
|
|
11
|
-
segments =
|
11
|
+
segments = tokenize_component_tags token.value
|
12
12
|
|
13
13
|
i = 0
|
14
14
|
while i < segments.count
|
@@ -22,9 +22,9 @@ module RBlade
|
|
22
22
|
i += 1
|
23
23
|
elsif segments[i] == "<" && segments[i + 1]&.match?(/x[-:]/)
|
24
24
|
name = segments[i + 1][2..]
|
25
|
-
raw_attributes = (segments[i + 2] != ">") ?
|
25
|
+
raw_attributes = (segments[i + 2] != ">") ? tokenize_attributes(segments[i + 2]) : nil
|
26
26
|
|
27
|
-
attributes =
|
27
|
+
attributes = process_attributes raw_attributes
|
28
28
|
|
29
29
|
if raw_attributes.nil?
|
30
30
|
segments.delete_at i + 1
|
@@ -54,7 +54,7 @@ module RBlade
|
|
54
54
|
|
55
55
|
private
|
56
56
|
|
57
|
-
def
|
57
|
+
def process_attributes(raw_attributes)
|
58
58
|
attributes = []
|
59
59
|
i = 0
|
60
60
|
while i < raw_attributes.count
|
@@ -84,7 +84,7 @@ module RBlade
|
|
84
84
|
end
|
85
85
|
|
86
86
|
# If the entire value is a single interpolated string, make this a ruby value
|
87
|
-
if attribute[:value]&.match?(/\A\{\{([^}]
|
87
|
+
if attribute[:value]&.match?(/\A\{\{([^}]++|(?!\}\})\})*\}\}\z/)
|
88
88
|
attribute[:type] = "ruby"
|
89
89
|
attribute[:name] = name
|
90
90
|
attribute[:value] = attribute[:value][2..-3]
|
@@ -112,75 +112,74 @@ module RBlade
|
|
112
112
|
attributes
|
113
113
|
end
|
114
114
|
|
115
|
-
def
|
115
|
+
def tokenize_component_tags(value)
|
116
116
|
value.split(%r/
|
117
117
|
# Opening and self-closing tags
|
118
118
|
(?:
|
119
119
|
(<)
|
120
|
-
\s
|
121
|
-
(x[-\:][\w\-\:\.]
|
120
|
+
\s*+
|
121
|
+
(x[-\:][\w\-\:\.]++)
|
122
122
|
((?:
|
123
|
-
\s
|
123
|
+
\s++
|
124
124
|
(?:
|
125
125
|
(?:
|
126
|
-
@class(\( (?:
|
126
|
+
@class(\( (?: [^()]++ | \g<-1> )*+ \))
|
127
127
|
)
|
128
128
|
|
|
129
129
|
(?:
|
130
|
-
@style(\( (?:
|
130
|
+
@style(\( (?: [^()]++ | \g<-1> )*+ \))
|
131
131
|
)
|
132
132
|
|
|
133
133
|
(
|
134
|
-
\{\{\s
|
134
|
+
\{\{ \s*+ attributes (?:[^}]++|\})*? \}\}
|
135
135
|
)
|
136
136
|
|
|
137
137
|
(?:
|
138
|
-
[\w\-:.@%]
|
138
|
+
[\w\-:.@%]++
|
139
139
|
(?:
|
140
140
|
=
|
141
141
|
(?:
|
142
|
-
"(
|
142
|
+
"(?> [^"{]++ | (?<!@)\{\{ (?:[^}]++|\})*? \}\} | \{ )*+"
|
143
143
|
|
|
144
|
-
'(
|
144
|
+
'(?> [^'{]++ | (?<!@)\{\{ (?:[^}]++|\})*? \}\} | \{ )*+'
|
145
145
|
|
|
146
|
-
(
|
146
|
+
(?> [^'"=<>\s\/{]++ | (?<!@)\{\{ (?:[^}]++|\})*? \}\} | \{ )++
|
147
147
|
)
|
148
148
|
)?
|
149
149
|
)
|
150
150
|
)
|
151
|
-
)
|
152
|
-
\s
|
153
|
-
(?<![=\-])
|
151
|
+
)*+)
|
152
|
+
\s*+
|
154
153
|
(\/?>)
|
155
154
|
)
|
156
155
|
|
|
157
156
|
# Closing tags
|
158
157
|
(?:
|
159
158
|
(<\/)
|
160
|
-
\s
|
161
|
-
(x[-\:][\w\-\:\.]
|
162
|
-
\s
|
159
|
+
\s*+
|
160
|
+
(x[-\:][\w\-\:\.]++)
|
161
|
+
\s*+
|
163
162
|
>
|
164
163
|
)
|
165
164
|
|
|
166
165
|
(<\/\/>)
|
167
|
-
/
|
166
|
+
/x)
|
168
167
|
end
|
169
168
|
|
170
|
-
def
|
169
|
+
def tokenize_attributes(segment)
|
171
170
|
segment.scan(%r/
|
172
171
|
(?<=\s|^)
|
173
172
|
(?:
|
174
173
|
(?:
|
175
|
-
(@class)(\( (?: (?>[^()]+) | \g<-1> )
|
174
|
+
(@class)(\( (?: (?>[^()]+) | \g<-1> )*+ \))
|
176
175
|
)
|
177
176
|
|
|
178
177
|
(?:
|
179
|
-
(@style)(\( (?: (?>[^()]+)| \g<-1> )
|
178
|
+
(@style)(\( (?: (?>[^()]+)| \g<-1> )*+ \))
|
180
179
|
)
|
181
180
|
|
|
182
181
|
(?:
|
183
|
-
(\{\{)\s
|
182
|
+
(\{\{) \s*+ (attributes(?:[^}\s]++|\}|\s)*?) \s*+ (\}\})
|
184
183
|
)
|
185
184
|
|
|
186
185
|
(?:
|
@@ -188,17 +187,17 @@ module RBlade
|
|
188
187
|
(?:
|
189
188
|
(=)
|
190
189
|
(?:
|
191
|
-
"((
|
190
|
+
"((?> [^"{]++ | (?<!@)\{\{ (?:[^}]++|\})*? \}\} | \{ )*+)"
|
192
191
|
|
|
193
|
-
'((
|
192
|
+
'((?> [^'{]++ | (?<!@)\{\{ (?:[^}]++|\})*? \}\} | \{ )*+)'
|
194
193
|
|
|
195
|
-
((
|
194
|
+
((?> [^'"=<>\s\/{]++ | (?<!@)\{\{(?:[^}]++|\})*?\}\} | \{ )*+)
|
196
195
|
)
|
197
196
|
)?
|
198
197
|
)
|
199
198
|
)
|
200
199
|
(?=\s|$)
|
201
|
-
/
|
200
|
+
/x).flatten.compact
|
202
201
|
end
|
203
202
|
end
|
204
203
|
end
|
@@ -14,27 +14,27 @@ module RBlade
|
|
14
14
|
(?:
|
15
15
|
(?:
|
16
16
|
(@@)
|
17
|
-
(\w
|
17
|
+
(\w++[!\?]?)
|
18
18
|
)
|
19
19
|
|
|
20
20
|
(?:
|
21
21
|
(@)
|
22
|
-
(\w
|
23
|
-
(?:([ \t]
|
24
|
-
(\(
|
22
|
+
(\w++[!\?]?)
|
23
|
+
(?:([ \t]*+)
|
24
|
+
(\([^)]*+\))
|
25
25
|
)?
|
26
26
|
)
|
27
27
|
)
|
28
28
|
(\s)?
|
29
|
-
/
|
29
|
+
/x)
|
30
30
|
|
31
|
-
|
31
|
+
parse_segments! segments
|
32
32
|
end.flatten!
|
33
33
|
end
|
34
34
|
|
35
35
|
private
|
36
36
|
|
37
|
-
def
|
37
|
+
def parse_segments!(segments)
|
38
38
|
i = 0
|
39
39
|
while i < segments.count
|
40
40
|
segment = segments[i]
|
@@ -46,12 +46,13 @@ module RBlade
|
|
46
46
|
|
47
47
|
i += 1
|
48
48
|
elsif segment == "@"
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
statement_handle = segments[i + 1].downcase.tr "_", ""
|
50
|
+
if CompilesStatements.has_handler(statement_handle)
|
51
|
+
tokenize_statement! statement_handle, segments, i
|
52
|
+
handle_special_cases! segments, i
|
52
53
|
|
53
|
-
segments.delete_at(i + 1) if segments[i + 1]&.match?(/\A\s\
|
54
|
-
if segments[i - 1].is_a?(Token) && segments[i - 1].type == :unprocessed && segments[i - 1].value.match?(/\A\s\
|
54
|
+
segments.delete_at(i + 1) if segments[i + 1]&.match?(/\A\s\z/)
|
55
|
+
if segments[i - 1].is_a?(Token) && segments[i - 1].type == :unprocessed && segments[i - 1].value.match?(/\A\s\z/)
|
55
56
|
segments.delete_at i - 1
|
56
57
|
i -= 1
|
57
58
|
end
|
@@ -60,7 +61,7 @@ module RBlade
|
|
60
61
|
segments[i] = Token.new(type: :unprocessed, value: segments[i] + segments[i + 1])
|
61
62
|
segments.delete_at i + 1
|
62
63
|
|
63
|
-
if segments.count > i + 2 && segments[i + 1].match?(/\A[ \t]
|
64
|
+
if segments.count > i + 2 && segments[i + 1].match?(/\A[ \t]*+\z/) && segments[i + 2][0] == "("
|
64
65
|
segments[i].value += segments[i + 1] + segments[i + 2]
|
65
66
|
segments.delete_at i + 1
|
66
67
|
segments.delete_at i + 1
|
@@ -83,19 +84,19 @@ module RBlade
|
|
83
84
|
segments
|
84
85
|
end
|
85
86
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
87
|
+
def tokenize_statement!(handle, segments, i)
|
88
|
+
segments.delete_at i + 1
|
89
|
+
statement_data = {name: handle}
|
89
90
|
|
90
91
|
# Remove optional whitespace
|
91
|
-
if segments.count > i + 2 && segments[i + 1].match?(/\A[ \t]
|
92
|
+
if segments.count > i + 2 && segments[i + 1].match?(/\A[ \t]*+\z/) && segments[i + 2][0] == "("
|
92
93
|
segments.delete_at i + 1
|
93
94
|
end
|
94
95
|
|
95
96
|
if segments.count > i + 1 && segments[i + 1][0] == "("
|
96
|
-
arguments =
|
97
|
+
arguments = tokenize_arguments! handle, segments, i + 1
|
97
98
|
|
98
|
-
|
99
|
+
unless arguments.nil?
|
99
100
|
statement_data[:arguments] = arguments
|
100
101
|
end
|
101
102
|
end
|
@@ -103,9 +104,8 @@ module RBlade
|
|
103
104
|
segments[i] = Token.new(type: :statement, value: statement_data)
|
104
105
|
end
|
105
106
|
|
106
|
-
def
|
107
|
-
|
108
|
-
when "case"
|
107
|
+
def handle_special_cases!(segments, i)
|
108
|
+
if segments[i][:value][:name] == "case"
|
109
109
|
# Remove any whitespace before a when statement
|
110
110
|
until segments[i + 1].nil? || segments[i + 1] == "@"
|
111
111
|
segments.delete_at i + 1
|
@@ -113,12 +113,12 @@ module RBlade
|
|
113
113
|
end
|
114
114
|
end
|
115
115
|
|
116
|
-
def
|
117
|
-
success =
|
116
|
+
def tokenize_arguments!(statement_handle, segments, segment_index)
|
117
|
+
success = expand_segment_to_end_parenthesis! segments, segment_index
|
118
118
|
|
119
119
|
# If no matching parentheses were found, so we combine the argument string with the next segment
|
120
|
-
|
121
|
-
|
120
|
+
unless success
|
121
|
+
unless segments[segment_index + 1].nil?
|
122
122
|
segments[segment_index] <<= segments[segment_index + 1]
|
123
123
|
segments.delete_at segment_index + 1
|
124
124
|
end
|
@@ -130,21 +130,20 @@ module RBlade
|
|
130
130
|
argument_string = segments[segment_index][1..-2]
|
131
131
|
|
132
132
|
# Special case for the props statement: remove the wrapping braces if they exist
|
133
|
-
if
|
133
|
+
if statement_handle == "props"
|
134
134
|
if argument_string.start_with?("{") && argument_string.end_with?("}")
|
135
135
|
argument_string = argument_string[1..-2]
|
136
136
|
end
|
137
137
|
end
|
138
138
|
|
139
|
-
arguments = Tokenizer.
|
139
|
+
arguments = Tokenizer.extract_comma_separated_values argument_string
|
140
140
|
segments.delete_at segment_index
|
141
141
|
|
142
142
|
arguments
|
143
143
|
end
|
144
144
|
|
145
|
-
def
|
145
|
+
def expand_segment_to_end_parenthesis!(segments, segment_index)
|
146
146
|
parentheses_difference = 0
|
147
|
-
tokens = nil
|
148
147
|
|
149
148
|
loop do
|
150
149
|
tokens = Ripper.lex(segments[segment_index]).map { |token| token[1] }
|
data/lib/rblade/compiler.rb
CHANGED
@@ -2,8 +2,7 @@
|
|
2
2
|
|
3
3
|
require "rblade/compiler/compiles_comments"
|
4
4
|
require "rblade/compiler/compiles_components"
|
5
|
-
require "rblade/compiler/
|
6
|
-
require "rblade/compiler/compiles_ruby"
|
5
|
+
require "rblade/compiler/compiles_injections"
|
7
6
|
require "rblade/compiler/compiles_verbatim"
|
8
7
|
require "rblade/compiler/compiles_statements"
|
9
8
|
require "rblade/compiler/tokenizes_components"
|
@@ -12,57 +11,59 @@ require "active_support/core_ext/string/output_safety"
|
|
12
11
|
|
13
12
|
Token = Struct.new(:type, :value)
|
14
13
|
|
15
|
-
if !defined?(h)
|
16
|
-
require "erb/escape"
|
17
|
-
define_method(:h, ERB::Escape.instance_method(:html_escape))
|
18
|
-
end
|
19
|
-
|
20
14
|
module RBlade
|
21
|
-
def self.escape_quotes
|
22
|
-
string
|
15
|
+
def self.escape_quotes(string)
|
16
|
+
string&.gsub(/['\\\x0]/, '\\\\\0')
|
23
17
|
end
|
24
18
|
|
25
19
|
class RBladeTemplateError < StandardError; end
|
26
20
|
|
27
|
-
# Register a new custom directive by providing a
|
21
|
+
# Register a new custom directive by providing a proc that will return a value to be output
|
28
22
|
#
|
29
23
|
# @param [String] name The directive tag without the "@", e.g. "if" for the "@if" directive
|
30
|
-
# @param [Proc] block The block that will return the compiled ruby code for the directive.
|
24
|
+
# @param [Proc] block The block that will return the compiled ruby code for the directive. Can accept `:args`, `:tokens` and `:token_index` as arguments.
|
31
25
|
# @return [void]
|
32
26
|
def self.register_directive_handler(name, &)
|
33
27
|
CompilesStatements.register_handler(name, &)
|
34
28
|
end
|
35
29
|
|
30
|
+
# Register a new custom directive by providing a proc that will return ruby code to add to the template. The code must end in a semi-colon.
|
31
|
+
#
|
32
|
+
# @param [String] name The directive tag without the "@", e.g. "if" for the "@if" directive
|
33
|
+
# @param [Proc] block The block that will return the compiled ruby code for the directive. Can accept `:args`, `:tokens` and `:token_index` as arguments.
|
34
|
+
# @return [void]
|
35
|
+
def self.register_raw_directive_handler(name, &)
|
36
|
+
CompilesStatements.register_raw_handler(name, &)
|
37
|
+
end
|
38
|
+
|
36
39
|
class Compiler
|
37
|
-
def self.
|
40
|
+
def self.compile_string(string_template, component_store)
|
38
41
|
tokens = [Token.new(:unprocessed, string_template)]
|
39
42
|
|
40
43
|
CompilesVerbatim.new.compile! tokens
|
41
44
|
CompilesComments.new.compile! tokens
|
42
|
-
CompilesRuby.new.compile! tokens
|
43
45
|
TokenizesComponents.new.tokenize! tokens
|
44
|
-
|
46
|
+
CompilesInjections.new.compile! tokens
|
45
47
|
TokenizesStatements.new.tokenize! tokens
|
46
48
|
CompilesStatements.new.compile! tokens
|
47
49
|
|
48
50
|
component_compiler = CompilesComponents.new(component_store)
|
49
51
|
component_compiler.compile! tokens
|
50
52
|
component_compiler.ensure_all_tags_closed
|
51
|
-
|
52
|
-
compileTokens tokens
|
53
|
+
compile_tokens tokens
|
53
54
|
end
|
54
55
|
|
55
|
-
def self.
|
56
|
+
def self.compile_attribute_string(string_template)
|
56
57
|
tokens = [Token.new(:unprocessed, string_template)]
|
57
58
|
|
58
59
|
CompilesComments.compile!(tokens)
|
59
60
|
CompilesRuby.compile! tokens
|
60
61
|
CompilesPrints.compile!(tokens)
|
61
62
|
|
62
|
-
|
63
|
+
compile_tokens tokens
|
63
64
|
end
|
64
65
|
|
65
|
-
def self.
|
66
|
+
def self.compile_tokens(tokens)
|
66
67
|
output = +""
|
67
68
|
|
68
69
|
i = 0
|
@@ -14,7 +14,7 @@ module RBlade
|
|
14
14
|
def component(full_name)
|
15
15
|
# If this is a relative path, prepend with the previous component name's base
|
16
16
|
if full_name.start_with? "."
|
17
|
-
full_name = @component_name_stack.last.
|
17
|
+
full_name = @component_name_stack.last.sub(/[^.]++\z/, "") + full_name.delete_prefix(".")
|
18
18
|
end
|
19
19
|
|
20
20
|
# Ensure each component is only compiled once
|
@@ -24,14 +24,7 @@ module RBlade
|
|
24
24
|
|
25
25
|
@component_name_stack << full_name
|
26
26
|
|
27
|
-
|
28
|
-
name = full_name
|
29
|
-
|
30
|
-
if name.match? "::"
|
31
|
-
namespace, name = full_name.split("::")
|
32
|
-
end
|
33
|
-
|
34
|
-
method_name = compile_component full_name, File.read(find_component_file(namespace, name))
|
27
|
+
method_name = compile_component full_name, File.read(find_component_file(full_name, @component_name_stack))
|
35
28
|
@component_name_stack.pop
|
36
29
|
|
37
30
|
method_name
|
@@ -43,31 +36,37 @@ module RBlade
|
|
43
36
|
path << "/"
|
44
37
|
end
|
45
38
|
|
46
|
-
|
47
|
-
|
39
|
+
template_paths[namespace] ||= []
|
40
|
+
template_paths[namespace] << path
|
48
41
|
end
|
49
42
|
|
50
43
|
def view_name(view_name)
|
51
44
|
@component_name_stack.push view_name
|
52
45
|
end
|
53
46
|
|
47
|
+
def current_view_name
|
48
|
+
@component_name_stack.last
|
49
|
+
end
|
50
|
+
|
54
51
|
def get
|
55
52
|
@component_definitions
|
56
53
|
end
|
57
54
|
|
58
|
-
|
55
|
+
def self.find_component_file(name, name_stack = nil)
|
56
|
+
if name.match? "::"
|
57
|
+
namespace, name = name.split("::", 2)
|
58
|
+
end
|
59
59
|
|
60
|
-
def find_component_file(namespace, name)
|
61
60
|
file_path = name.tr ".", "/"
|
62
61
|
|
63
|
-
|
62
|
+
template_paths[namespace]&.each do |base_path|
|
64
63
|
FILE_EXTENSIONS.each do |extension|
|
65
64
|
if File.exist? base_path + file_path + extension
|
66
65
|
return "#{base_path}#{file_path}#{extension}"
|
67
66
|
end
|
68
67
|
if File.exist? base_path + file_path + "/index" + extension
|
69
68
|
# Account for index files for relative components
|
70
|
-
|
69
|
+
name_stack << name_stack.pop + ".index" if name_stack
|
71
70
|
return "#{base_path}#{file_path}/index#{extension}"
|
72
71
|
end
|
73
72
|
end
|
@@ -75,6 +74,9 @@ module RBlade
|
|
75
74
|
|
76
75
|
raise RBladeTemplateError.new "Unknown component #{namespace}::#{name}"
|
77
76
|
end
|
77
|
+
delegate :find_component_file, to: :class
|
78
|
+
|
79
|
+
private
|
78
80
|
|
79
81
|
def compile_component(name, template)
|
80
82
|
escaped_name = name.gsub(/[^0-9a-zA-Z_]/) do |match|
|
@@ -82,15 +84,13 @@ module RBlade
|
|
82
84
|
(match == ".") ? "__" : "_#{match.unpack1("H*")}_"
|
83
85
|
end
|
84
86
|
|
85
|
-
compiled_component = RBlade::Compiler.
|
86
|
-
|
87
|
-
slot_assignment = compiled_component.match?(/\Wslot\W/) ? "slot=" : ""
|
87
|
+
compiled_component = RBlade::Compiler.compile_string(template, self)
|
88
88
|
|
89
|
-
@component_definitions << "def self._rblade_component_#{escaped_name}(attributes,&)
|
89
|
+
@component_definitions << "def self._rblade_component_#{escaped_name}(attributes,&);slot=if block_given?;RBlade::SlotManager.new(@output_buffer.capture(->(name, slot_attributes, &slot_block)do;attributes[name]=RBlade::SlotManager.new(@output_buffer.capture(&slot_block), slot_attributes);end,&));end;_stacks=[];@output_buffer.raw_buffer<<@output_buffer.capture do;#{compiled_component}@output_buffer.raw_buffer.prepend(@_rblade_stack_manager.get(_stacks));end;end;"
|
90
90
|
|
91
91
|
@component_method_names[name] = "_rblade_component_#{escaped_name}"
|
92
92
|
end
|
93
93
|
|
94
|
-
|
94
|
+
cattr_accessor :template_paths, default: {}
|
95
95
|
end
|
96
96
|
end
|
@@ -2,8 +2,9 @@
|
|
2
2
|
|
3
3
|
module RBlade
|
4
4
|
class AttributesManager
|
5
|
-
|
6
|
-
|
5
|
+
delegate :delete, to: :@attributes
|
6
|
+
|
7
|
+
def initialize(attributes)
|
7
8
|
@attributes = attributes
|
8
9
|
end
|
9
10
|
|
@@ -37,11 +38,11 @@ module RBlade
|
|
37
38
|
true
|
38
39
|
end
|
39
40
|
|
40
|
-
def to_str
|
41
|
+
def to_str(attributes = nil)
|
41
42
|
attributes ||= @attributes
|
42
43
|
|
43
44
|
attributes.map do |key, value|
|
44
|
-
(value == true) ? key : "#{key}=\"#{
|
45
|
+
(value == true) ? key : "#{key}=\"#{CGI.escape_html(value.to_s)}\""
|
45
46
|
end.join(" ")
|
46
47
|
end
|
47
48
|
|
@@ -72,7 +73,7 @@ module RBlade
|
|
72
73
|
def class(new_classes)
|
73
74
|
new_classes = ClassManager.new(new_classes).to_s
|
74
75
|
attributes = @attributes.dup
|
75
|
-
attributes[:class] =
|
76
|
+
attributes[:class] = merge_classes attributes[:class], new_classes
|
76
77
|
|
77
78
|
AttributesManager.new attributes
|
78
79
|
end
|
@@ -82,12 +83,12 @@ module RBlade
|
|
82
83
|
|
83
84
|
@attributes.each do |key, value|
|
84
85
|
if key == :class && !new_attributes[key].nil?
|
85
|
-
new_attributes[key] =
|
86
|
+
new_attributes[key] = merge_classes(new_attributes[key], value.to_s)
|
86
87
|
next
|
87
88
|
end
|
88
89
|
|
89
90
|
if key == :style && !new_attributes[key].nil?
|
90
|
-
new_attributes[key] =
|
91
|
+
new_attributes[key] = merge_styles(new_attributes[key], value.to_s)
|
91
92
|
next
|
92
93
|
end
|
93
94
|
|
@@ -105,7 +106,7 @@ module RBlade
|
|
105
106
|
|
106
107
|
private
|
107
108
|
|
108
|
-
def
|
109
|
+
def merge_classes(classes_1, classes_2)
|
109
110
|
if classes_1.nil?
|
110
111
|
return classes_2
|
111
112
|
end
|
@@ -122,7 +123,7 @@ module RBlade
|
|
122
123
|
classes_combined
|
123
124
|
end
|
124
125
|
|
125
|
-
def
|
126
|
+
def merge_styles(styles_1, styles_2)
|
126
127
|
if styles_1.nil?
|
127
128
|
return styles_2
|
128
129
|
end
|
@@ -4,7 +4,7 @@ require "rblade/helpers/attributes_manager"
|
|
4
4
|
|
5
5
|
module RBlade
|
6
6
|
class SlotManager
|
7
|
-
def initialize
|
7
|
+
def initialize(content, attributes = nil)
|
8
8
|
@content = content
|
9
9
|
@attributes = attributes && AttributesManager.new(attributes)
|
10
10
|
end
|
@@ -30,7 +30,7 @@ module RBlade
|
|
30
30
|
end
|
31
31
|
|
32
32
|
# Wraps var in a slot manager if it's a string
|
33
|
-
def self.wrap
|
33
|
+
def self.wrap(var)
|
34
34
|
var.is_a?(String) ? new(var) : var
|
35
35
|
end
|
36
36
|
|
@@ -40,7 +40,7 @@ module RBlade
|
|
40
40
|
@stack = +""
|
41
41
|
end
|
42
42
|
|
43
|
-
def set_before_stack
|
43
|
+
def set_before_stack(before_stack)
|
44
44
|
@before_stack = before_stack
|
45
45
|
end
|
46
46
|
|
@@ -52,11 +52,11 @@ module RBlade
|
|
52
52
|
to_s
|
53
53
|
end
|
54
54
|
|
55
|
-
def push
|
55
|
+
def push(code)
|
56
56
|
@stack << code
|
57
57
|
end
|
58
58
|
|
59
|
-
def prepend
|
59
|
+
def prepend(code)
|
60
60
|
@prepends << code
|
61
61
|
end
|
62
62
|
end
|