herb 0.8.10-arm-linux-gnu → 0.9.1-arm-linux-gnu
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/Makefile +11 -3
- data/README.md +64 -34
- data/Rakefile +48 -40
- data/config.yml +473 -34
- data/ext/herb/error_helpers.c +535 -140
- data/ext/herb/error_helpers.h +1 -0
- data/ext/herb/extconf.rb +67 -28
- data/ext/herb/extension.c +321 -51
- data/ext/herb/extension.h +1 -0
- data/ext/herb/extension_helpers.c +24 -14
- data/ext/herb/extension_helpers.h +2 -2
- data/ext/herb/nodes.c +647 -270
- data/ext/herb/nodes.h +1 -0
- data/herb.gemspec +3 -2
- data/lib/herb/3.0/herb.so +0 -0
- data/lib/herb/3.1/herb.so +0 -0
- data/lib/herb/3.2/herb.so +0 -0
- data/lib/herb/3.3/herb.so +0 -0
- data/lib/herb/3.4/herb.so +0 -0
- data/lib/herb/4.0/herb.so +0 -0
- data/lib/herb/ast/helpers.rb +3 -3
- data/lib/herb/ast/node.rb +15 -2
- data/lib/herb/ast/nodes.rb +1530 -179
- data/lib/herb/bootstrap.rb +87 -0
- data/lib/herb/cli.rb +341 -31
- data/lib/herb/configuration.rb +248 -0
- data/lib/herb/defaults.yml +32 -0
- data/lib/herb/engine/compiler.rb +78 -11
- data/lib/herb/engine/debug_visitor.rb +13 -3
- data/lib/herb/engine/error_formatter.rb +13 -9
- data/lib/herb/engine/parser_error_overlay.rb +10 -6
- data/lib/herb/engine/validator.rb +8 -3
- data/lib/herb/engine/validators/nesting_validator.rb +2 -2
- data/lib/herb/engine.rb +119 -43
- data/lib/herb/errors.rb +808 -88
- data/lib/herb/lex_result.rb +1 -0
- data/lib/herb/location.rb +7 -3
- data/lib/herb/parse_result.rb +12 -2
- data/lib/herb/parser_options.rb +62 -0
- data/lib/herb/position.rb +1 -0
- data/lib/herb/prism_inspect.rb +120 -0
- data/lib/herb/project.rb +923 -331
- data/lib/herb/range.rb +1 -0
- data/lib/herb/token.rb +7 -1
- data/lib/herb/version.rb +1 -1
- data/lib/herb/visitor.rb +47 -2
- data/lib/herb/warnings.rb +6 -1
- data/lib/herb.rb +35 -3
- data/sig/herb/ast/helpers.rbs +2 -2
- data/sig/herb/ast/node.rbs +12 -2
- data/sig/herb/ast/nodes.rbs +773 -128
- data/sig/herb/bootstrap.rbs +31 -0
- data/sig/herb/configuration.rbs +89 -0
- data/sig/herb/engine/compiler.rbs +9 -1
- data/sig/herb/engine/debug_visitor.rbs +2 -0
- data/sig/herb/engine/validator.rbs +5 -1
- data/sig/herb/engine.rbs +21 -3
- data/sig/herb/errors.rbs +372 -63
- data/sig/herb/location.rbs +4 -0
- data/sig/herb/parse_result.rbs +4 -2
- data/sig/herb/parser_options.rbs +46 -0
- data/sig/herb/position.rbs +1 -0
- data/sig/herb/prism_inspect.rbs +28 -0
- data/sig/herb/range.rbs +1 -0
- data/sig/herb/token.rbs +6 -0
- data/sig/herb/visitor.rbs +31 -4
- data/sig/herb/warnings.rbs +6 -1
- data/sig/herb.rbs +14 -0
- data/sig/herb_c_extension.rbs +5 -2
- data/sig/rubyvm.rbs +5 -0
- data/sig/serialized_ast_errors.rbs +82 -6
- data/sig/serialized_ast_nodes.rbs +91 -6
- data/src/analyze/action_view/attribute_extraction_helpers.c +303 -0
- data/src/analyze/action_view/content_tag.c +78 -0
- data/src/analyze/action_view/link_to.c +167 -0
- data/src/analyze/action_view/registry.c +83 -0
- data/src/analyze/action_view/tag.c +70 -0
- data/src/analyze/action_view/tag_helper_node_builders.c +305 -0
- data/src/analyze/action_view/tag_helpers.c +815 -0
- data/src/analyze/action_view/turbo_frame_tag.c +88 -0
- data/src/analyze/analyze.c +885 -0
- data/src/{analyzed_ruby.c → analyze/analyzed_ruby.c} +13 -11
- data/src/analyze/builders.c +343 -0
- data/src/analyze/conditional_elements.c +594 -0
- data/src/analyze/conditional_open_tags.c +640 -0
- data/src/analyze/control_type.c +250 -0
- data/src/{analyze_helpers.c → analyze/helpers.c} +48 -23
- data/src/analyze/invalid_structures.c +193 -0
- data/src/{analyze_missing_end.c → analyze/missing_end.c} +33 -22
- data/src/analyze/parse_errors.c +84 -0
- data/src/analyze/prism_annotate.c +399 -0
- data/src/analyze/render_nodes.c +761 -0
- data/src/{analyze_transform.c → analyze/transform.c} +24 -3
- data/src/ast_node.c +17 -7
- data/src/ast_nodes.c +759 -387
- data/src/ast_pretty_print.c +264 -6
- data/src/errors.c +1454 -519
- data/src/extract.c +145 -49
- data/src/herb.c +52 -34
- data/src/html_util.c +241 -12
- data/src/include/analyze/action_view/attribute_extraction_helpers.h +36 -0
- data/src/include/analyze/action_view/tag_helper_handler.h +43 -0
- data/src/include/analyze/action_view/tag_helper_node_builders.h +70 -0
- data/src/include/analyze/action_view/tag_helpers.h +38 -0
- data/src/include/{analyze.h → analyze/analyze.h} +14 -4
- data/src/include/{analyzed_ruby.h → analyze/analyzed_ruby.h} +3 -3
- data/src/include/analyze/builders.h +27 -0
- data/src/include/analyze/conditional_elements.h +9 -0
- data/src/include/analyze/conditional_open_tags.h +9 -0
- data/src/include/analyze/control_type.h +14 -0
- data/src/include/{analyze_helpers.h → analyze/helpers.h} +4 -2
- data/src/include/analyze/invalid_structures.h +11 -0
- data/src/include/analyze/prism_annotate.h +16 -0
- data/src/include/analyze/render_nodes.h +11 -0
- data/src/include/ast_node.h +11 -5
- data/src/include/ast_nodes.h +154 -38
- data/src/include/ast_pretty_print.h +5 -0
- data/src/include/element_source.h +3 -8
- data/src/include/errors.h +206 -55
- data/src/include/extract.h +21 -5
- data/src/include/herb.h +18 -6
- data/src/include/herb_prism_node.h +13 -0
- data/src/include/html_util.h +7 -2
- data/src/include/io.h +3 -1
- data/src/include/lex_helpers.h +29 -0
- data/src/include/lexer.h +1 -1
- data/src/include/lexer_peek_helpers.h +87 -13
- data/src/include/lexer_struct.h +2 -0
- data/src/include/location.h +2 -1
- data/src/include/parser.h +28 -2
- data/src/include/parser_helpers.h +19 -3
- data/src/include/pretty_print.h +10 -5
- data/src/include/prism_context.h +45 -0
- data/src/include/prism_helpers.h +10 -7
- data/src/include/prism_serialized.h +12 -0
- data/src/include/token.h +16 -4
- data/src/include/token_struct.h +10 -3
- data/src/include/utf8.h +2 -1
- data/src/include/util/hb_allocator.h +78 -0
- data/src/include/util/hb_arena.h +6 -1
- data/src/include/util/hb_arena_debug.h +12 -1
- data/src/include/util/hb_array.h +7 -3
- data/src/include/util/hb_buffer.h +6 -4
- data/src/include/util/hb_foreach.h +79 -0
- data/src/include/util/hb_narray.h +8 -4
- data/src/include/util/hb_string.h +56 -9
- data/src/include/util.h +6 -3
- data/src/include/version.h +1 -1
- data/src/io.c +3 -2
- data/src/lexer.c +42 -30
- data/src/lexer_peek_helpers.c +12 -74
- data/src/location.c +2 -2
- data/src/main.c +53 -28
- data/src/parser.c +784 -247
- data/src/parser_helpers.c +110 -23
- data/src/parser_match_tags.c +129 -48
- data/src/pretty_print.c +29 -24
- data/src/prism_helpers.c +30 -27
- data/src/ruby_parser.c +2 -0
- data/src/token.c +151 -66
- data/src/token_matchers.c +0 -1
- data/src/utf8.c +7 -6
- data/src/util/hb_allocator.c +341 -0
- data/src/util/hb_arena.c +81 -56
- data/src/util/hb_arena_debug.c +32 -17
- data/src/util/hb_array.c +30 -15
- data/src/util/hb_buffer.c +17 -21
- data/src/util/hb_narray.c +22 -7
- data/src/util/hb_string.c +49 -35
- data/src/util.c +21 -11
- data/src/visitor.c +67 -0
- data/templates/ext/herb/error_helpers.c.erb +24 -11
- data/templates/ext/herb/error_helpers.h.erb +1 -0
- data/templates/ext/herb/nodes.c.erb +50 -16
- data/templates/ext/herb/nodes.h.erb +1 -0
- data/templates/java/error_helpers.c.erb +1 -1
- data/templates/java/nodes.c.erb +30 -8
- data/templates/java/org/herb/ast/Errors.java.erb +24 -1
- data/templates/java/org/herb/ast/Nodes.java.erb +80 -21
- data/templates/javascript/packages/core/src/errors.ts.erb +16 -3
- data/templates/javascript/packages/core/src/node-type-guards.ts.erb +3 -1
- data/templates/javascript/packages/core/src/nodes.ts.erb +109 -32
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +13 -4
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +43 -4
- data/templates/lib/herb/ast/nodes.rb.erb +95 -32
- data/templates/lib/herb/errors.rb.erb +15 -3
- data/templates/lib/herb/visitor.rb.erb +2 -2
- data/templates/rust/src/ast/nodes.rs.erb +97 -44
- data/templates/rust/src/errors.rs.erb +2 -1
- data/templates/rust/src/nodes.rs.erb +168 -16
- data/templates/rust/src/union_types.rs.erb +60 -0
- data/templates/rust/src/visitor.rs.erb +81 -0
- data/templates/src/{analyze_missing_end.c.erb → analyze/missing_end.c.erb} +9 -6
- data/templates/src/{analyze_transform.c.erb → analyze/transform.c.erb} +2 -2
- data/templates/src/ast_nodes.c.erb +34 -26
- data/templates/src/ast_pretty_print.c.erb +24 -5
- data/templates/src/errors.c.erb +60 -54
- data/templates/src/include/ast_nodes.h.erb +6 -2
- data/templates/src/include/ast_pretty_print.h.erb +5 -0
- data/templates/src/include/errors.h.erb +15 -11
- data/templates/src/include/util/hb_foreach.h.erb +20 -0
- data/templates/src/parser_match_tags.c.erb +10 -4
- data/templates/src/visitor.c.erb +2 -2
- data/templates/template.rb +204 -29
- data/templates/wasm/error_helpers.cpp.erb +9 -5
- data/templates/wasm/nodes.cpp.erb +41 -4
- metadata +60 -16
- data/src/analyze.c +0 -1608
- data/src/element_source.c +0 -12
- data/src/include/util/hb_system.h +0 -9
- data/src/util/hb_system.c +0 -30
data/lib/herb/engine.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
# typed: false
|
|
2
3
|
|
|
3
4
|
require "json"
|
|
4
5
|
require "time"
|
|
@@ -17,7 +18,7 @@ require_relative "engine/validators/accessibility_validator"
|
|
|
17
18
|
module Herb
|
|
18
19
|
class Engine
|
|
19
20
|
attr_reader :src, :filename, :project_path, :relative_file_path, :bufvar, :debug, :content_for_head,
|
|
20
|
-
:validation_error_template, :visitors
|
|
21
|
+
:validation_error_template, :visitors, :enabled_validators
|
|
21
22
|
|
|
22
23
|
ESCAPE_TABLE = {
|
|
23
24
|
"&" => "&",
|
|
@@ -30,6 +31,16 @@ module Herb
|
|
|
30
31
|
class CompilationError < StandardError
|
|
31
32
|
end
|
|
32
33
|
|
|
34
|
+
class InvalidRubyError < CompilationError
|
|
35
|
+
attr_reader :compiled_source
|
|
36
|
+
|
|
37
|
+
def initialize(message, compiled_source: nil)
|
|
38
|
+
@compiled_source = compiled_source
|
|
39
|
+
|
|
40
|
+
super(message)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
33
44
|
def initialize(input, properties = {})
|
|
34
45
|
@filename = properties[:filename] ? ::Pathname.new(properties[:filename]) : nil
|
|
35
46
|
@project_path = ::Pathname.new(properties[:project_path] || Dir.pwd)
|
|
@@ -51,6 +62,8 @@ module Herb
|
|
|
51
62
|
@content_for_head = properties[:content_for_head]
|
|
52
63
|
@validation_error_template = nil
|
|
53
64
|
@validation_mode = properties.fetch(:validation_mode, :raise)
|
|
65
|
+
@enabled_validators = Herb.configuration.enabled_validators(properties[:validators] || {})
|
|
66
|
+
@strict = properties.fetch(:strict, true)
|
|
54
67
|
@visitors = properties.fetch(:visitors, default_visitors)
|
|
55
68
|
|
|
56
69
|
if @debug && @visitors.empty?
|
|
@@ -75,6 +88,8 @@ module Herb
|
|
|
75
88
|
preamble = properties[:preamble] || "#{@bufvar} = #{bufval};"
|
|
76
89
|
postamble = properties[:postamble] || "#{@bufvar}.to_s\n"
|
|
77
90
|
|
|
91
|
+
preamble = "#{preamble}; " unless preamble.empty? || preamble.end_with?(";", " ", "\n")
|
|
92
|
+
|
|
78
93
|
@src << "# frozen_string_literal: true\n" if @freeze
|
|
79
94
|
|
|
80
95
|
if properties[:ensure]
|
|
@@ -89,7 +104,7 @@ module Herb
|
|
|
89
104
|
@src << "__herb = ::Herb::Engine; " if @escape && @escapefunc == "__herb.h"
|
|
90
105
|
@src << preamble
|
|
91
106
|
|
|
92
|
-
parse_result = ::Herb.parse(input, track_whitespace: true)
|
|
107
|
+
parse_result = ::Herb.parse(input, track_whitespace: true, strict: @strict)
|
|
93
108
|
ast = parse_result.value
|
|
94
109
|
parser_errors = parse_result.errors
|
|
95
110
|
|
|
@@ -104,12 +119,12 @@ module Herb
|
|
|
104
119
|
# Skip both errors and compilation, but still need minimal Ruby code
|
|
105
120
|
end
|
|
106
121
|
else
|
|
107
|
-
|
|
108
|
-
all_errors = parser_errors + (validation_errors || [])
|
|
122
|
+
validators = run_validation(ast) unless @validation_mode == :none
|
|
109
123
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
124
|
+
if validators
|
|
125
|
+
handle_validation_errors(validators, input) if @validation_mode == :raise
|
|
126
|
+
add_validation_overlay(validators, input) if @validation_mode == :overlay
|
|
127
|
+
end
|
|
113
128
|
|
|
114
129
|
@visitors.each do |visitor|
|
|
115
130
|
ast.accept(visitor)
|
|
@@ -132,6 +147,10 @@ module Herb
|
|
|
132
147
|
|
|
133
148
|
@src << "; ensure\n #{@bufvar} = __original_outvar\nend\n" if properties[:ensure]
|
|
134
149
|
|
|
150
|
+
if properties.fetch(:validate_ruby, false)
|
|
151
|
+
ensure_valid_ruby!(@src)
|
|
152
|
+
end
|
|
153
|
+
|
|
135
154
|
@src.freeze
|
|
136
155
|
freeze
|
|
137
156
|
end
|
|
@@ -172,6 +191,14 @@ module Herb
|
|
|
172
191
|
end
|
|
173
192
|
end
|
|
174
193
|
|
|
194
|
+
def self.comment?(code)
|
|
195
|
+
code.include?("#")
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def self.heredoc?(code)
|
|
199
|
+
code.match?(/<<[~-]?\s*['"`]?\w/)
|
|
200
|
+
end
|
|
201
|
+
|
|
175
202
|
protected
|
|
176
203
|
|
|
177
204
|
def add_text(text)
|
|
@@ -193,8 +220,8 @@ module Herb
|
|
|
193
220
|
@src << " " << code
|
|
194
221
|
|
|
195
222
|
# TODO: rework and check for Prism::InlineComment as soon as we expose the Prism Nodes in the Herb AST
|
|
196
|
-
if code.
|
|
197
|
-
@src << "\n"
|
|
223
|
+
if self.class.comment?(code) || self.class.heredoc?(code)
|
|
224
|
+
@src << "\n" unless code[-1] == "\n"
|
|
198
225
|
else
|
|
199
226
|
@src << ";" unless code[-1] == "\n"
|
|
200
227
|
end
|
|
@@ -203,48 +230,82 @@ module Herb
|
|
|
203
230
|
@buffer_on_stack = false
|
|
204
231
|
end
|
|
205
232
|
|
|
233
|
+
def expression_block?
|
|
234
|
+
@_in_expression_block || false
|
|
235
|
+
end
|
|
236
|
+
|
|
206
237
|
def add_expression(indicator, code)
|
|
207
|
-
|
|
208
|
-
|
|
238
|
+
unescaped = (indicator == "=") ^ @escape
|
|
239
|
+
|
|
240
|
+
if expression_block?
|
|
241
|
+
unescaped ? add_expression_block_result(code) : add_expression_block_result_escaped(code)
|
|
209
242
|
else
|
|
210
|
-
add_expression_result_escaped(code)
|
|
243
|
+
unescaped ? add_expression_result(code) : add_expression_result_escaped(code)
|
|
211
244
|
end
|
|
212
245
|
end
|
|
213
246
|
|
|
214
247
|
def add_expression_result(code)
|
|
215
248
|
with_buffer {
|
|
216
|
-
@src << " << (" << code <<
|
|
249
|
+
@src << " << (" << code << trailing_newline(code) << ").to_s"
|
|
217
250
|
}
|
|
218
251
|
end
|
|
219
252
|
|
|
220
253
|
def add_expression_result_escaped(code)
|
|
221
254
|
with_buffer {
|
|
222
|
-
@src << " << " << @escapefunc << "((" << code <<
|
|
255
|
+
@src << " << " << @escapefunc << "((" << code << trailing_newline(code) << "))"
|
|
223
256
|
}
|
|
224
257
|
end
|
|
225
258
|
|
|
226
259
|
def add_expression_block(indicator, code)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
260
|
+
@_in_expression_block = true
|
|
261
|
+
@_expression_block_open_paren = false
|
|
262
|
+
|
|
263
|
+
add_expression(indicator, code)
|
|
264
|
+
ensure
|
|
265
|
+
@_in_expression_block = false
|
|
232
266
|
end
|
|
233
267
|
|
|
234
268
|
def add_expression_block_result(code)
|
|
269
|
+
@_expression_block_open_paren = true
|
|
270
|
+
|
|
235
271
|
with_buffer {
|
|
236
|
-
@src << " << " << code <<
|
|
272
|
+
@src << " << (" << code << trailing_newline(code)
|
|
237
273
|
}
|
|
238
274
|
end
|
|
239
275
|
|
|
240
276
|
def add_expression_block_result_escaped(code)
|
|
277
|
+
@_expression_block_open_paren = true
|
|
278
|
+
|
|
241
279
|
with_buffer {
|
|
242
|
-
@src << " << " << @escapefunc << "(" << code <<
|
|
280
|
+
@src << " << " << @escapefunc << "((" << code << trailing_newline(code)
|
|
243
281
|
}
|
|
244
282
|
end
|
|
245
283
|
|
|
246
|
-
def
|
|
247
|
-
|
|
284
|
+
def add_expression_block_end(code, escaped: false)
|
|
285
|
+
if @_expression_block_open_paren
|
|
286
|
+
terminate_expression
|
|
287
|
+
|
|
288
|
+
trailing_newline = code.end_with?("\n")
|
|
289
|
+
code_stripped = code.chomp
|
|
290
|
+
|
|
291
|
+
@src.chomp! if @src.end_with?("\n") && code_stripped.start_with?(" ")
|
|
292
|
+
|
|
293
|
+
@src << " " << code_stripped
|
|
294
|
+
@src << "\n" if self.class.comment?(code_stripped)
|
|
295
|
+
@src << (escaped ? "))" : ")")
|
|
296
|
+
@src << (trailing_newline ? "\n" : ";")
|
|
297
|
+
|
|
298
|
+
@buffer_on_stack = false
|
|
299
|
+
else
|
|
300
|
+
add_code(code)
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def trailing_newline(code)
|
|
305
|
+
return "\n" if self.class.comment?(code)
|
|
306
|
+
return "\n" if self.class.heredoc?(code)
|
|
307
|
+
|
|
308
|
+
""
|
|
248
309
|
end
|
|
249
310
|
|
|
250
311
|
def add_postamble(postamble)
|
|
@@ -272,19 +333,16 @@ module Herb
|
|
|
272
333
|
|
|
273
334
|
def run_validation(ast)
|
|
274
335
|
validators = [
|
|
275
|
-
Validators::SecurityValidator.new,
|
|
276
|
-
Validators::NestingValidator.new,
|
|
277
|
-
Validators::AccessibilityValidator.new
|
|
336
|
+
Validators::SecurityValidator.new(enabled: @enabled_validators[:security]),
|
|
337
|
+
Validators::NestingValidator.new(enabled: @enabled_validators[:nesting]),
|
|
338
|
+
Validators::AccessibilityValidator.new(enabled: @enabled_validators[:accessibility])
|
|
278
339
|
]
|
|
279
340
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
validators.each do |validator|
|
|
341
|
+
validators.select(&:enabled?).each do |validator|
|
|
283
342
|
ast.accept(validator)
|
|
284
|
-
errors.concat(validator.errors)
|
|
285
343
|
end
|
|
286
344
|
|
|
287
|
-
|
|
345
|
+
validators
|
|
288
346
|
end
|
|
289
347
|
|
|
290
348
|
def handle_parser_errors(parser_errors, input, _ast)
|
|
@@ -304,24 +362,19 @@ module Herb
|
|
|
304
362
|
end
|
|
305
363
|
end
|
|
306
364
|
|
|
307
|
-
def handle_validation_errors(
|
|
365
|
+
def handle_validation_errors(validators, input)
|
|
366
|
+
errors = validators.select(&:enabled?).flat_map(&:errors)
|
|
308
367
|
return unless errors.any?
|
|
309
368
|
|
|
310
|
-
security_error = errors.find { |error|
|
|
311
|
-
error.is_a?(Hash) && error[:source] == "SecurityValidator"
|
|
312
|
-
}
|
|
369
|
+
security_error = errors.find { |error| error[:source] == "SecurityValidator" }
|
|
313
370
|
|
|
314
371
|
if security_error
|
|
315
|
-
line = security_error[:location]&.start&.line
|
|
316
|
-
column = security_error[:location]&.start&.column
|
|
317
|
-
suggestion = security_error[:suggestion]
|
|
318
|
-
|
|
319
372
|
raise SecurityError.new(
|
|
320
373
|
security_error[:message],
|
|
321
|
-
line: line,
|
|
322
|
-
column: column,
|
|
374
|
+
line: security_error[:location]&.start&.line,
|
|
375
|
+
column: security_error[:location]&.start&.column,
|
|
323
376
|
filename: @filename,
|
|
324
|
-
suggestion: suggestion
|
|
377
|
+
suggestion: security_error[:suggestion]
|
|
325
378
|
)
|
|
326
379
|
end
|
|
327
380
|
|
|
@@ -330,7 +383,8 @@ module Herb
|
|
|
330
383
|
raise CompilationError, "\n#{message}"
|
|
331
384
|
end
|
|
332
385
|
|
|
333
|
-
def add_validation_overlay(
|
|
386
|
+
def add_validation_overlay(validators, input = nil)
|
|
387
|
+
errors = validators.select(&:enabled?).flat_map(&:errors)
|
|
334
388
|
return unless errors.any?
|
|
335
389
|
|
|
336
390
|
templates = errors.map { |error|
|
|
@@ -393,5 +447,27 @@ module Herb
|
|
|
393
447
|
def default_visitors
|
|
394
448
|
[]
|
|
395
449
|
end
|
|
450
|
+
|
|
451
|
+
def ensure_valid_ruby!(source)
|
|
452
|
+
RubyVM::InstructionSequence.compile(source)
|
|
453
|
+
rescue SyntaxError => e
|
|
454
|
+
return if e.message.include?("Invalid yield")
|
|
455
|
+
|
|
456
|
+
begin
|
|
457
|
+
require "prism"
|
|
458
|
+
rescue LoadError
|
|
459
|
+
# Prism not available, fall through
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
raise InvalidRubyError.new("Compiled template produced invalid Ruby:\n - #{e.message}", compiled_source: @src) unless defined?(Prism)
|
|
463
|
+
|
|
464
|
+
prism_result = Prism.parse(@src)
|
|
465
|
+
syntax_errors = prism_result.errors.reject { |error| error.type == :invalid_yield }
|
|
466
|
+
|
|
467
|
+
if syntax_errors.any?
|
|
468
|
+
details = syntax_errors.map { |err| " - #{err.message} (line #{err.location.start_line})" }.join("\n")
|
|
469
|
+
raise InvalidRubyError.new("Compiled template produced invalid Ruby:\n#{details}", compiled_source: @src)
|
|
470
|
+
end
|
|
471
|
+
end
|
|
396
472
|
end
|
|
397
473
|
end
|