herb 0.7.5 → 0.8.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/Makefile +8 -5
- data/config.yml +26 -6
- data/ext/herb/error_helpers.c +57 -3
- data/ext/herb/error_helpers.h +1 -1
- data/ext/herb/extconf.rb +1 -0
- data/ext/herb/extension.c +10 -24
- data/ext/herb/extension_helpers.c +3 -3
- data/ext/herb/extension_helpers.h +1 -1
- data/ext/herb/nodes.c +72 -37
- data/herb.gemspec +0 -2
- data/lib/herb/ast/helpers.rb +11 -0
- data/lib/herb/ast/node.rb +15 -6
- data/lib/herb/ast/nodes.rb +609 -392
- data/lib/herb/cli.rb +31 -0
- data/lib/herb/colors.rb +82 -0
- data/lib/herb/engine/compiler.rb +140 -14
- data/lib/herb/engine/debug_visitor.rb +1 -5
- data/lib/herb/engine/parser_error_overlay.rb +1 -1
- data/lib/herb/engine.rb +8 -14
- data/lib/herb/errors.rb +166 -56
- data/lib/herb/location.rb +2 -2
- data/lib/herb/project.rb +86 -21
- data/lib/herb/token.rb +14 -2
- data/lib/herb/version.rb +1 -1
- data/lib/herb.rb +1 -0
- data/sig/herb/ast/helpers.rbs +3 -0
- data/sig/herb/ast/node.rbs +12 -5
- data/sig/herb/ast/nodes.rbs +124 -62
- data/sig/herb/colors.rbs +35 -0
- data/sig/herb/engine/compiler.rbs +23 -1
- data/sig/herb/errors.rbs +74 -20
- data/sig/herb/token.rbs +8 -0
- data/sig/herb_c_extension.rbs +1 -1
- data/sig/serialized_ast_errors.rbs +8 -0
- data/src/analyze.c +420 -171
- data/src/analyze_helpers.c +5 -0
- data/src/analyze_missing_end.c +147 -0
- data/src/analyze_transform.c +196 -0
- data/src/analyzed_ruby.c +23 -2
- data/src/ast_node.c +5 -5
- data/src/ast_nodes.c +179 -179
- data/src/ast_pretty_print.c +232 -232
- data/src/element_source.c +7 -6
- data/src/errors.c +246 -126
- data/src/extract.c +92 -34
- data/src/herb.c +37 -49
- data/src/html_util.c +34 -96
- data/src/include/analyze.h +10 -2
- data/src/include/analyze_helpers.h +3 -0
- data/src/include/analyzed_ruby.h +4 -2
- data/src/include/ast_node.h +2 -2
- data/src/include/ast_nodes.h +67 -66
- data/src/include/ast_pretty_print.h +2 -2
- data/src/include/element_source.h +3 -1
- data/src/include/errors.h +30 -14
- data/src/include/extract.h +4 -4
- data/src/include/herb.h +6 -7
- data/src/include/html_util.h +4 -5
- data/src/include/lexer.h +1 -3
- data/src/include/lexer_peek_helpers.h +14 -14
- data/src/include/lexer_struct.h +3 -2
- data/src/include/macros.h +4 -0
- data/src/include/parser.h +12 -6
- data/src/include/parser_helpers.h +25 -15
- data/src/include/pretty_print.h +38 -28
- data/src/include/token.h +5 -8
- data/src/include/utf8.h +3 -2
- data/src/include/util/hb_arena.h +31 -0
- data/src/include/util/hb_arena_debug.h +8 -0
- data/src/include/util/hb_array.h +33 -0
- data/src/include/util/hb_buffer.h +34 -0
- data/src/include/util/hb_string.h +29 -0
- data/src/include/util/hb_system.h +9 -0
- data/src/include/util.h +3 -14
- data/src/include/version.h +1 -1
- data/src/include/visitor.h +1 -1
- data/src/io.c +7 -4
- data/src/lexer.c +61 -88
- data/src/lexer_peek_helpers.c +35 -37
- data/src/main.c +19 -23
- data/src/parser.c +282 -201
- data/src/parser_helpers.c +46 -40
- data/src/parser_match_tags.c +316 -0
- data/src/pretty_print.c +82 -106
- data/src/token.c +18 -65
- data/src/utf8.c +4 -4
- data/src/util/hb_arena.c +179 -0
- data/src/util/hb_arena_debug.c +237 -0
- data/src/{array.c → util/hb_array.c} +26 -27
- data/src/util/hb_buffer.c +203 -0
- data/src/util/hb_string.c +85 -0
- data/src/util/hb_system.c +30 -0
- data/src/util.c +29 -99
- data/src/visitor.c +54 -54
- data/templates/ext/herb/error_helpers.c.erb +3 -3
- data/templates/ext/herb/error_helpers.h.erb +1 -1
- data/templates/ext/herb/nodes.c.erb +11 -6
- data/templates/java/error_helpers.c.erb +75 -0
- data/templates/java/error_helpers.h.erb +20 -0
- data/templates/java/nodes.c.erb +97 -0
- data/templates/java/nodes.h.erb +23 -0
- data/templates/java/org/herb/ast/Errors.java.erb +121 -0
- data/templates/java/org/herb/ast/NodeVisitor.java.erb +14 -0
- data/templates/java/org/herb/ast/Nodes.java.erb +220 -0
- data/templates/java/org/herb/ast/Visitor.java.erb +56 -0
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +8 -8
- data/templates/javascript/packages/node/extension/error_helpers.h.erb +1 -1
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +9 -9
- data/templates/javascript/packages/node/extension/nodes.h.erb +1 -1
- data/templates/lib/herb/ast/nodes.rb.erb +28 -16
- data/templates/lib/herb/errors.rb.erb +17 -12
- data/templates/rust/src/ast/nodes.rs.erb +220 -0
- data/templates/rust/src/errors.rs.erb +216 -0
- data/templates/rust/src/nodes.rs.erb +374 -0
- data/templates/src/analyze_missing_end.c.erb +36 -0
- data/templates/src/analyze_transform.c.erb +24 -0
- data/templates/src/ast_nodes.c.erb +14 -14
- data/templates/src/ast_pretty_print.c.erb +36 -36
- data/templates/src/errors.c.erb +31 -31
- data/templates/src/include/ast_nodes.h.erb +10 -9
- data/templates/src/include/ast_pretty_print.h.erb +2 -2
- data/templates/src/include/errors.h.erb +6 -6
- data/templates/src/parser_match_tags.c.erb +38 -0
- data/templates/src/visitor.c.erb +4 -4
- data/templates/template.rb +22 -3
- data/templates/wasm/error_helpers.cpp.erb +9 -9
- data/templates/wasm/error_helpers.h.erb +1 -1
- data/templates/wasm/nodes.cpp.erb +9 -9
- data/templates/wasm/nodes.h.erb +1 -1
- data/vendor/prism/Rakefile +4 -1
- data/vendor/prism/config.yml +2 -1
- data/vendor/prism/include/prism/ast.h +31 -1
- data/vendor/prism/include/prism/diagnostic.h +1 -0
- data/vendor/prism/include/prism/version.h +3 -3
- data/vendor/prism/src/diagnostic.c +3 -1
- data/vendor/prism/src/prism.c +130 -71
- data/vendor/prism/src/util/pm_string.c +6 -8
- data/vendor/prism/templates/include/prism/ast.h.erb +2 -0
- data/vendor/prism/templates/java/org/prism/Loader.java.erb +2 -2
- data/vendor/prism/templates/javascript/src/deserialize.js.erb +2 -2
- data/vendor/prism/templates/lib/prism/serialize.rb.erb +2 -2
- data/vendor/prism/templates/sig/prism.rbs.erb +4 -0
- data/vendor/prism/templates/src/diagnostic.c.erb +1 -0
- metadata +34 -20
- data/lib/herb/libherb/array.rb +0 -51
- data/lib/herb/libherb/ast_node.rb +0 -50
- data/lib/herb/libherb/buffer.rb +0 -56
- data/lib/herb/libherb/extract_result.rb +0 -20
- data/lib/herb/libherb/lex_result.rb +0 -32
- data/lib/herb/libherb/libherb.rb +0 -52
- data/lib/herb/libherb/parse_result.rb +0 -20
- data/lib/herb/libherb/token.rb +0 -46
- data/lib/herb/libherb.rb +0 -35
- data/src/buffer.c +0 -241
- data/src/include/array.h +0 -33
- data/src/include/buffer.h +0 -39
- data/src/include/json.h +0 -28
- data/src/include/memory.h +0 -12
- data/src/json.c +0 -205
- data/src/memory.c +0 -53
data/lib/herb/cli.rb
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
require "optparse"
|
|
7
7
|
|
|
8
8
|
class Herb::CLI
|
|
9
|
+
include Herb::Colors
|
|
10
|
+
|
|
9
11
|
attr_accessor :json, :silent, :no_interactive, :no_log_file, :no_timing, :local, :escape, :no_escape, :freeze, :debug
|
|
10
12
|
|
|
11
13
|
def initialize(args)
|
|
@@ -27,6 +29,8 @@ class Herb::CLI
|
|
|
27
29
|
puts result.value.to_json
|
|
28
30
|
else
|
|
29
31
|
puts result.value.inspect
|
|
32
|
+
|
|
33
|
+
print_error_summary(result.errors) if @command == "parse" && result.respond_to?(:errors) && result.errors.any?
|
|
30
34
|
end
|
|
31
35
|
end
|
|
32
36
|
|
|
@@ -223,6 +227,33 @@ class Herb::CLI
|
|
|
223
227
|
|
|
224
228
|
private
|
|
225
229
|
|
|
230
|
+
def print_error_summary(errors)
|
|
231
|
+
puts
|
|
232
|
+
puts white("#{bold(red("Errors"))} #{dimmed("(#{errors.size} total)")}")
|
|
233
|
+
puts
|
|
234
|
+
|
|
235
|
+
errors.each_with_index do |error, index|
|
|
236
|
+
error_type = error.error_name
|
|
237
|
+
error_location = format_location_for_copy(error.location)
|
|
238
|
+
error_message = error.message
|
|
239
|
+
|
|
240
|
+
puts white(" #{bold("#{index + 1}.")} #{bold(red(error_type))} #{dimmed("at #{error_location}")}")
|
|
241
|
+
puts white(" #{error_message}")
|
|
242
|
+
puts unless index == errors.size - 1
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def format_location_for_copy(location)
|
|
247
|
+
line = location.start.line
|
|
248
|
+
column = location.start.column
|
|
249
|
+
|
|
250
|
+
if @file
|
|
251
|
+
"#{@file}:#{line}:#{column}"
|
|
252
|
+
else
|
|
253
|
+
"#{line}:#{column}"
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
226
257
|
def compile_template
|
|
227
258
|
require_relative "engine"
|
|
228
259
|
|
data/lib/herb/colors.rb
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: true
|
|
3
|
+
|
|
4
|
+
# rbs_inline: enabled
|
|
5
|
+
|
|
6
|
+
module Herb
|
|
7
|
+
module Colors
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
#: () -> bool
|
|
11
|
+
def enabled?
|
|
12
|
+
return false if ENV["NO_COLOR"]
|
|
13
|
+
return false if defined?(IRB)
|
|
14
|
+
return false if defined?(Minitest)
|
|
15
|
+
|
|
16
|
+
$stdout.tty?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
#: (String) -> String
|
|
20
|
+
def white(string)
|
|
21
|
+
return string unless enabled?
|
|
22
|
+
|
|
23
|
+
"\e[37m#{string}\e[0m"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
#: (String) -> String
|
|
27
|
+
def yellow(string)
|
|
28
|
+
return string unless enabled?
|
|
29
|
+
|
|
30
|
+
"\e[33m#{string}\e[0m"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
#: (String) -> String
|
|
34
|
+
def green(string)
|
|
35
|
+
return string unless enabled?
|
|
36
|
+
|
|
37
|
+
"\e[32m#{string}\e[0m"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
#: (String) -> String
|
|
41
|
+
def red(string)
|
|
42
|
+
return string unless enabled?
|
|
43
|
+
|
|
44
|
+
"\e[31m#{string}\e[0m"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
#: (String) -> String
|
|
48
|
+
def magenta(string)
|
|
49
|
+
return string unless enabled?
|
|
50
|
+
|
|
51
|
+
"\e[35m#{string}\e[0m"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#: (String) -> String
|
|
55
|
+
def cyan(string)
|
|
56
|
+
return string unless enabled?
|
|
57
|
+
|
|
58
|
+
"\e[36m#{string}\e[0m"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
#: (String) -> String
|
|
62
|
+
def bright_magenta(string)
|
|
63
|
+
return string unless enabled?
|
|
64
|
+
|
|
65
|
+
"\e[95m#{string}\e[0m"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
#: (String) -> String
|
|
69
|
+
def dimmed(string)
|
|
70
|
+
return string unless enabled?
|
|
71
|
+
|
|
72
|
+
"\e[2m#{string}\e[0m"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
#: (String) -> String
|
|
76
|
+
def bold(string)
|
|
77
|
+
return string unless enabled?
|
|
78
|
+
|
|
79
|
+
"\e[1m#{string}\e[0m"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
data/lib/herb/engine/compiler.rb
CHANGED
|
@@ -10,6 +10,9 @@ module Herb
|
|
|
10
10
|
|
|
11
11
|
@engine = engine
|
|
12
12
|
@escape = options.fetch(:escape) { options.fetch(:escape_html, false) }
|
|
13
|
+
@attrfunc = options.fetch(:attrfunc, @escape ? "__herb.attr" : "::Herb::Engine.attr")
|
|
14
|
+
@jsfunc = options.fetch(:jsfunc, @escape ? "__herb.js" : "::Herb::Engine.js")
|
|
15
|
+
@cssfunc = options.fetch(:cssfunc, @escape ? "__herb.css" : "::Herb::Engine.css")
|
|
13
16
|
@tokens = [] #: Array[untyped]
|
|
14
17
|
@element_stack = [] #: Array[String]
|
|
15
18
|
@context_stack = [:html_content]
|
|
@@ -83,7 +86,7 @@ module Herb
|
|
|
83
86
|
end
|
|
84
87
|
|
|
85
88
|
def visit_html_attribute_node(node)
|
|
86
|
-
|
|
89
|
+
add_whitespace(" ")
|
|
87
90
|
|
|
88
91
|
visit(node.name)
|
|
89
92
|
|
|
@@ -131,7 +134,7 @@ module Herb
|
|
|
131
134
|
end
|
|
132
135
|
|
|
133
136
|
def visit_whitespace_node(node)
|
|
134
|
-
|
|
137
|
+
add_whitespace(node.value.value)
|
|
135
138
|
end
|
|
136
139
|
|
|
137
140
|
def visit_html_comment_node(node)
|
|
@@ -159,11 +162,13 @@ module Herb
|
|
|
159
162
|
end
|
|
160
163
|
|
|
161
164
|
def visit_erb_content_node(node)
|
|
165
|
+
return if inline_ruby_comment?(node)
|
|
166
|
+
|
|
162
167
|
process_erb_tag(node)
|
|
163
168
|
end
|
|
164
169
|
|
|
165
170
|
def visit_erb_control_node(node, &_block)
|
|
166
|
-
|
|
171
|
+
apply_trim(node, node.content.value.strip)
|
|
167
172
|
|
|
168
173
|
yield if block_given?
|
|
169
174
|
end
|
|
@@ -227,7 +232,7 @@ module Herb
|
|
|
227
232
|
end
|
|
228
233
|
|
|
229
234
|
def visit_erb_case_match_node(node)
|
|
230
|
-
visit_erb_control_with_parts(node, :
|
|
235
|
+
visit_erb_control_with_parts(node, :conditions, :else_clause, :end_node)
|
|
231
236
|
end
|
|
232
237
|
|
|
233
238
|
def visit_erb_in_node(node)
|
|
@@ -294,11 +299,17 @@ module Herb
|
|
|
294
299
|
def add_context_aware_expression(code, context)
|
|
295
300
|
case context
|
|
296
301
|
when :attribute_value
|
|
297
|
-
@engine.send(:with_buffer) {
|
|
302
|
+
@engine.send(:with_buffer) {
|
|
303
|
+
@engine.src << " << #{@attrfunc}((" << code << "))"
|
|
304
|
+
}
|
|
298
305
|
when :script_content
|
|
299
|
-
@engine.send(:with_buffer) {
|
|
306
|
+
@engine.send(:with_buffer) {
|
|
307
|
+
@engine.src << " << #{@jsfunc}((" << code << "))"
|
|
308
|
+
}
|
|
300
309
|
when :style_content
|
|
301
|
-
@engine.send(:with_buffer) {
|
|
310
|
+
@engine.send(:with_buffer) {
|
|
311
|
+
@engine.src << " << #{@cssfunc}((" << code << "))"
|
|
312
|
+
}
|
|
302
313
|
else
|
|
303
314
|
@engine.send(:add_expression_result_escaped, code)
|
|
304
315
|
end
|
|
@@ -314,17 +325,15 @@ module Herb
|
|
|
314
325
|
if erb_output?(opening)
|
|
315
326
|
process_erb_output(opening, code)
|
|
316
327
|
else
|
|
317
|
-
|
|
328
|
+
apply_trim(node, code)
|
|
318
329
|
end
|
|
319
|
-
|
|
320
|
-
handle_whitespace_trimming(node)
|
|
321
330
|
end
|
|
322
331
|
|
|
323
332
|
def add_text(text)
|
|
324
333
|
return if text.empty?
|
|
325
334
|
|
|
326
335
|
if @trim_next_whitespace
|
|
327
|
-
text = text.
|
|
336
|
+
text = text.sub(/\A[ \t]*\r?\n/, "")
|
|
328
337
|
@trim_next_whitespace = false
|
|
329
338
|
end
|
|
330
339
|
|
|
@@ -333,6 +342,10 @@ module Herb
|
|
|
333
342
|
@tokens << [:text, text, current_context]
|
|
334
343
|
end
|
|
335
344
|
|
|
345
|
+
def add_whitespace(whitespace)
|
|
346
|
+
@tokens << [:whitespace, whitespace, current_context]
|
|
347
|
+
end
|
|
348
|
+
|
|
336
349
|
def add_code(code)
|
|
337
350
|
@tokens << [:code, code, current_context]
|
|
338
351
|
end
|
|
@@ -348,11 +361,13 @@ module Herb
|
|
|
348
361
|
def optimize_tokens(tokens)
|
|
349
362
|
return tokens if tokens.empty?
|
|
350
363
|
|
|
364
|
+
compacted = compact_whitespace_tokens(tokens)
|
|
365
|
+
|
|
351
366
|
optimized = [] #: Array[untyped]
|
|
352
367
|
current_text = ""
|
|
353
368
|
current_context = nil
|
|
354
369
|
|
|
355
|
-
|
|
370
|
+
compacted.each do |type, value, context|
|
|
356
371
|
if type == :text
|
|
357
372
|
current_text += value
|
|
358
373
|
current_context ||= context
|
|
@@ -373,6 +388,56 @@ module Herb
|
|
|
373
388
|
optimized
|
|
374
389
|
end
|
|
375
390
|
|
|
391
|
+
def compact_whitespace_tokens(tokens)
|
|
392
|
+
return tokens if tokens.empty?
|
|
393
|
+
|
|
394
|
+
tokens.map.with_index { |token, index|
|
|
395
|
+
next token unless token[0] == :whitespace
|
|
396
|
+
|
|
397
|
+
next nil if adjacent_whitespace?(tokens, index)
|
|
398
|
+
next nil if whitespace_before_code_sequence?(tokens, index)
|
|
399
|
+
|
|
400
|
+
[:text, token[1], token[2]]
|
|
401
|
+
}.compact
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def adjacent_whitespace?(tokens, index)
|
|
405
|
+
prev_token = index.positive? ? tokens[index - 1] : nil
|
|
406
|
+
next_token = index < tokens.length - 1 ? tokens[index + 1] : nil
|
|
407
|
+
|
|
408
|
+
trailing_whitespace?(prev_token) || leading_whitespace?(next_token)
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
def trailing_whitespace?(token)
|
|
412
|
+
return false unless token
|
|
413
|
+
|
|
414
|
+
token[0] == :whitespace || (token[0] == :text && token[1] =~ /\s\z/)
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
def leading_whitespace?(token)
|
|
418
|
+
token && token[0] == :text && token[1] =~ /\A\s/
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
def whitespace_before_code_sequence?(tokens, current_index)
|
|
422
|
+
previous_token = tokens[current_index - 1] if current_index.positive?
|
|
423
|
+
|
|
424
|
+
return false unless previous_token && previous_token[0] == :code
|
|
425
|
+
|
|
426
|
+
token_before_code = find_token_before_code_sequence(tokens, current_index)
|
|
427
|
+
|
|
428
|
+
return false unless token_before_code
|
|
429
|
+
|
|
430
|
+
trailing_whitespace?(token_before_code)
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
def find_token_before_code_sequence(tokens, whitespace_index)
|
|
434
|
+
search_index = whitespace_index - 1
|
|
435
|
+
|
|
436
|
+
search_index -= 1 while search_index >= 0 && tokens[search_index][0] == :code
|
|
437
|
+
|
|
438
|
+
search_index >= 0 ? tokens[search_index] : nil
|
|
439
|
+
end
|
|
440
|
+
|
|
376
441
|
def process_erb_output(opening, code)
|
|
377
442
|
should_escape = should_escape_output?(opening)
|
|
378
443
|
add_expression_with_escaping(code, should_escape)
|
|
@@ -391,8 +456,69 @@ module Herb
|
|
|
391
456
|
end
|
|
392
457
|
end
|
|
393
458
|
|
|
394
|
-
def
|
|
395
|
-
@
|
|
459
|
+
def at_line_start?
|
|
460
|
+
@tokens.empty? ||
|
|
461
|
+
@tokens.last[0] != :text ||
|
|
462
|
+
@tokens.last[1].empty? ||
|
|
463
|
+
@tokens.last[1].end_with?("\n") ||
|
|
464
|
+
@tokens.last[1] =~ /\A[ \t]+\z/ ||
|
|
465
|
+
@tokens.last[1] =~ /\n[ \t]+\z/
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
def extract_lspace
|
|
469
|
+
return "" unless @tokens.last && @tokens.last[0] == :text
|
|
470
|
+
|
|
471
|
+
text = @tokens.last[1]
|
|
472
|
+
|
|
473
|
+
return Regexp.last_match(1) if text =~ /\n([ \t]+)\z/ || text =~ /\A([ \t]+)\z/
|
|
474
|
+
|
|
475
|
+
""
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
def extract_and_remove_lspace!
|
|
479
|
+
lspace = extract_lspace
|
|
480
|
+
return lspace if lspace.empty?
|
|
481
|
+
|
|
482
|
+
text = @tokens.last[1]
|
|
483
|
+
if text =~ /\n[ \t]+\z/
|
|
484
|
+
text.sub!(/[ \t]+\z/, "")
|
|
485
|
+
elsif text =~ /\A[ \t]+\z/
|
|
486
|
+
text.replace("")
|
|
487
|
+
end
|
|
488
|
+
@tokens.last[1] = text
|
|
489
|
+
|
|
490
|
+
lspace
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
def apply_trim(node, code)
|
|
494
|
+
has_left_trim = node.tag_opening.value.start_with?("<%-")
|
|
495
|
+
node.tag_closing&.value
|
|
496
|
+
|
|
497
|
+
remove_trailing_whitespace_from_last_token! if has_left_trim
|
|
498
|
+
|
|
499
|
+
if at_line_start?
|
|
500
|
+
lspace = extract_and_remove_lspace!
|
|
501
|
+
rspace = " \n"
|
|
502
|
+
|
|
503
|
+
@tokens << [:code, "#{lspace}#{code}#{rspace}", current_context]
|
|
504
|
+
@trim_next_whitespace = true
|
|
505
|
+
else
|
|
506
|
+
@tokens << [:code, code, current_context]
|
|
507
|
+
end
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
def remove_trailing_whitespace_from_last_token!
|
|
511
|
+
return unless @tokens.last && @tokens.last[0] == :text
|
|
512
|
+
|
|
513
|
+
text = @tokens.last[1]
|
|
514
|
+
|
|
515
|
+
if text =~ /\n[ \t]+\z/
|
|
516
|
+
text.sub!(/[ \t]+\z/, "")
|
|
517
|
+
@tokens.last[1] = text
|
|
518
|
+
elsif text =~ /\A[ \t]+\z/
|
|
519
|
+
text.replace("")
|
|
520
|
+
@tokens.last[1] = text
|
|
521
|
+
end
|
|
396
522
|
end
|
|
397
523
|
end
|
|
398
524
|
end
|
|
@@ -180,9 +180,7 @@ module Herb
|
|
|
180
180
|
debug_attributes << create_debug_attribute("data-herb-debug-attach-to-parent", "true")
|
|
181
181
|
end
|
|
182
182
|
|
|
183
|
-
debug_attributes
|
|
184
|
-
open_tag_node.children << attr
|
|
185
|
-
end
|
|
183
|
+
open_tag_node.children.concat(debug_attributes)
|
|
186
184
|
|
|
187
185
|
@debug_attributes_applied = true
|
|
188
186
|
end
|
|
@@ -233,9 +231,7 @@ module Herb
|
|
|
233
231
|
]
|
|
234
232
|
|
|
235
233
|
debug_attributes << create_debug_attribute("data-herb-debug-line", line.to_s) if line
|
|
236
|
-
|
|
237
234
|
debug_attributes << create_debug_attribute("data-herb-debug-column", (column + 1).to_s) if column
|
|
238
|
-
|
|
239
235
|
debug_attributes << create_debug_attribute("style", "display: contents;")
|
|
240
236
|
|
|
241
237
|
tag_name_token = create_token(:tag_name, "span")
|
data/lib/herb/engine.rb
CHANGED
|
@@ -43,7 +43,7 @@ module Herb
|
|
|
43
43
|
|
|
44
44
|
@bufvar = properties[:bufvar] || properties[:outvar] || "_buf"
|
|
45
45
|
@escape = properties.fetch(:escape) { properties.fetch(:escape_html, false) }
|
|
46
|
-
@escapefunc = properties
|
|
46
|
+
@escapefunc = properties.fetch(:escapefunc, @escape ? "__herb.h" : "::Herb::Engine.h")
|
|
47
47
|
@src = properties[:src] || String.new
|
|
48
48
|
@chain_appends = properties[:chain_appends]
|
|
49
49
|
@buffer_on_stack = false
|
|
@@ -67,12 +67,6 @@ module Herb
|
|
|
67
67
|
"validation_mode must be one of :raise, :overlay, or :none, got #{@validation_mode.inspect}"
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
-
@escapefunc ||= if @escape
|
|
71
|
-
"__herb.h"
|
|
72
|
-
else
|
|
73
|
-
"::Herb::Engine.h"
|
|
74
|
-
end
|
|
75
|
-
|
|
76
70
|
@freeze = properties[:freeze]
|
|
77
71
|
@freeze_template_literals = properties.fetch(:freeze_template_literals, true)
|
|
78
72
|
@text_end = @freeze_template_literals ? "'.freeze" : "'"
|
|
@@ -93,11 +87,9 @@ module Herb
|
|
|
93
87
|
end
|
|
94
88
|
|
|
95
89
|
@src << "__herb = ::Herb::Engine; " if @escape && @escapefunc == "__herb.h"
|
|
96
|
-
|
|
97
90
|
@src << preamble
|
|
98
|
-
@src << "\n" unless preamble.end_with?("\n")
|
|
99
91
|
|
|
100
|
-
parse_result = ::Herb.parse(input)
|
|
92
|
+
parse_result = ::Herb.parse(input, track_whitespace: true)
|
|
101
93
|
ast = parse_result.value
|
|
102
94
|
parser_errors = parse_result.errors
|
|
103
95
|
|
|
@@ -136,7 +128,7 @@ module Herb
|
|
|
136
128
|
end
|
|
137
129
|
|
|
138
130
|
@src << "\n" unless @src.end_with?("\n")
|
|
139
|
-
|
|
131
|
+
add_postamble(postamble)
|
|
140
132
|
|
|
141
133
|
@src << "; ensure\n #{@bufvar} = __original_outvar\nend\n" if properties[:ensure]
|
|
142
134
|
|
|
@@ -196,6 +188,8 @@ module Herb
|
|
|
196
188
|
if code.include?("=begin") || code.include?("=end")
|
|
197
189
|
@src << "\n" << code << "\n"
|
|
198
190
|
else
|
|
191
|
+
@src.chomp! if @src.end_with?("\n") && code.start_with?(" ") && !code.end_with?("\n")
|
|
192
|
+
|
|
199
193
|
@src << " " << code
|
|
200
194
|
|
|
201
195
|
# TODO: rework and check for Prism::InlineComment as soon as we expose the Prism Nodes in the Herb AST
|
|
@@ -291,10 +285,10 @@ module Herb
|
|
|
291
285
|
when :overlay
|
|
292
286
|
add_parser_error_overlay(parser_errors, input)
|
|
293
287
|
@src << "\n" unless @src.end_with?("\n")
|
|
294
|
-
|
|
288
|
+
add_postamble("#{@bufvar}.to_s\n")
|
|
295
289
|
when :none
|
|
296
290
|
@src << "\n" unless @src.end_with?("\n")
|
|
297
|
-
|
|
291
|
+
add_postamble("#{@bufvar}.to_s\n")
|
|
298
292
|
end
|
|
299
293
|
end
|
|
300
294
|
|
|
@@ -350,7 +344,7 @@ module Herb
|
|
|
350
344
|
data-filename="#{escape_attr(@relative_file_path)}"
|
|
351
345
|
data-message="#{escaped_message}"
|
|
352
346
|
#{"data-suggestion=\"#{escaped_suggestion}\"" if error[:suggestion]}
|
|
353
|
-
data-timestamp="#{Time.now.iso8601}"
|
|
347
|
+
data-timestamp="#{Time.now.utc.iso8601}"
|
|
354
348
|
>#{html_fragment}</template>
|
|
355
349
|
TEMPLATE
|
|
356
350
|
}.join
|