herb 0.6.1-x86-linux-musl → 0.7.0-x86-linux-musl
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/README.md +1 -0
- data/ext/herb/nodes.c +6 -4
- 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/ast/helpers.rb +26 -0
- data/lib/herb/ast/nodes.rb +7 -3
- data/lib/herb/cli.rb +158 -1
- data/lib/herb/engine/compiler.rb +399 -0
- data/lib/herb/engine/debug_visitor.rb +321 -0
- data/lib/herb/engine/error_formatter.rb +420 -0
- data/lib/herb/engine/parser_error_overlay.rb +767 -0
- data/lib/herb/engine/validation_error_overlay.rb +182 -0
- data/lib/herb/engine/validation_errors.rb +65 -0
- data/lib/herb/engine/validator.rb +75 -0
- data/lib/herb/engine/validators/accessibility_validator.rb +31 -0
- data/lib/herb/engine/validators/nesting_validator.rb +95 -0
- data/lib/herb/engine/validators/security_validator.rb +71 -0
- data/lib/herb/engine.rb +366 -0
- data/lib/herb/project.rb +3 -3
- data/lib/herb/version.rb +1 -1
- data/lib/herb/visitor.rb +2 -0
- data/lib/herb.rb +2 -0
- data/sig/herb/ast/helpers.rbs +16 -0
- data/sig/herb/ast/nodes.rbs +4 -2
- data/sig/herb/engine/compiler.rbs +109 -0
- data/sig/herb/engine/debug.rbs +38 -0
- data/sig/herb/engine/debug_visitor.rbs +70 -0
- data/sig/herb/engine/error_formatter.rbs +47 -0
- data/sig/herb/engine/parser_error_overlay.rbs +41 -0
- data/sig/herb/engine/validation_error_overlay.rbs +35 -0
- data/sig/herb/engine/validation_errors.rbs +45 -0
- data/sig/herb/engine/validator.rbs +37 -0
- data/sig/herb/engine/validators/accessibility_validator.rbs +19 -0
- data/sig/herb/engine/validators/nesting_validator.rbs +25 -0
- data/sig/herb/engine/validators/security_validator.rbs +23 -0
- data/sig/herb/engine.rbs +72 -0
- data/sig/herb/visitor.rbs +2 -0
- data/sig/herb_c_extension.rbs +7 -0
- data/sig/serialized_ast_nodes.rbs +1 -0
- data/src/ast_nodes.c +2 -1
- data/src/ast_pretty_print.c +2 -1
- data/src/element_source.c +11 -0
- data/src/include/ast_nodes.h +3 -1
- data/src/include/element_source.h +13 -0
- data/src/include/version.h +1 -1
- data/src/parser.c +3 -0
- data/src/parser_helpers.c +1 -0
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c817e048425267d57d7e86f1e8ee6c08a283458435a1d1bd13cf8ec42d1722b
|
4
|
+
data.tar.gz: 1461dcca1670e4315755aa5364c31c7cbefc8ee5f8b7f8746e7a88f5e96040b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d8e07da38c1c0400a3bf8e7cd06cd70e0b737268d30c778efef7bb603027c281e8cf0d761c202a895888a0003353ca89aa5d4eb163d08cad0bec9a83e13d11b
|
7
|
+
data.tar.gz: bf2f61abf772b93cb77e7405dfdc5e0e2bf1870c642941ff6c9484b9c8a52a440dc8993e89ed614f84397f3880b1f0fbed73c11404d926d72f3ef1af91fcf9d0
|
data/README.md
CHANGED
@@ -127,6 +127,7 @@ While Herb brings a fresh approach to HTML+ERB tooling, it builds upon and learn
|
|
127
127
|
- [**htmlbeautifier**](https://github.com/threedaymonk/htmlbeautifier)
|
128
128
|
- [**vscode-erb-beautify**](https://github.com/aliariff/vscode-erb-beautify)
|
129
129
|
- [**vscode-erb-linter**](https://github.com/manuelpuyol/vscode-erb-linter)
|
130
|
+
- [**syntax_tree-erb**](https://github.com/davidwessman/syntax_tree-erb)
|
130
131
|
|
131
132
|
Herb differentiates itself by being HTML-aware from the ground up, providing a unified parsing approach that understands both HTML and ERB as first-class citizens, rather than treating one as embedded within the other.
|
132
133
|
|
data/ext/herb/nodes.c
CHANGED
@@ -151,8 +151,9 @@ static VALUE rb_html_element_node_from_c_struct(AST_HTML_ELEMENT_NODE_T* html_el
|
|
151
151
|
VALUE html_element_node_body = rb_nodes_array_from_c_array(html_element_node->body);
|
152
152
|
VALUE html_element_node_close_tag = rb_node_from_c_struct((AST_NODE_T*) html_element_node->close_tag);
|
153
153
|
VALUE html_element_node_is_void = (html_element_node->is_void) ? Qtrue : Qfalse;
|
154
|
+
VALUE html_element_node_source = rb_str_new_cstr(element_source_to_string(html_element_node->source));
|
154
155
|
|
155
|
-
VALUE args[
|
156
|
+
VALUE args[9] = {
|
156
157
|
type,
|
157
158
|
location,
|
158
159
|
errors,
|
@@ -160,10 +161,11 @@ static VALUE rb_html_element_node_from_c_struct(AST_HTML_ELEMENT_NODE_T* html_el
|
|
160
161
|
html_element_node_tag_name,
|
161
162
|
html_element_node_body,
|
162
163
|
html_element_node_close_tag,
|
163
|
-
html_element_node_is_void
|
164
|
+
html_element_node_is_void,
|
165
|
+
html_element_node_source
|
164
166
|
};
|
165
167
|
|
166
|
-
return rb_class_new_instance(
|
168
|
+
return rb_class_new_instance(9, args, HTMLElementNode);
|
167
169
|
};
|
168
170
|
|
169
171
|
static VALUE rb_html_attribute_value_node_from_c_struct(AST_HTML_ATTRIBUTE_VALUE_NODE_T* html_attribute_value_node) {
|
@@ -443,7 +445,7 @@ static VALUE rb_erb_content_node_from_c_struct(AST_ERB_CONTENT_NODE_T* erb_conte
|
|
443
445
|
VALUE erb_content_node_tag_opening = rb_token_from_c_struct(erb_content_node->tag_opening);
|
444
446
|
VALUE erb_content_node_content = rb_token_from_c_struct(erb_content_node->content);
|
445
447
|
VALUE erb_content_node_tag_closing = rb_token_from_c_struct(erb_content_node->tag_closing);
|
446
|
-
/* #<Herb::Template::AnalyzedRubyField:
|
448
|
+
/* #<Herb::Template::AnalyzedRubyField:0x00007f1e10166f68 @name="analyzed_ruby", @options={kind: nil}> */
|
447
449
|
VALUE erb_content_node_analyzed_ruby = Qnil;
|
448
450
|
VALUE erb_content_node_parsed = (erb_content_node->parsed) ? Qtrue : Qfalse;
|
449
451
|
VALUE erb_content_node_valid = (erb_content_node->valid) ? Qtrue : Qfalse;
|
data/lib/herb/3.0/herb.so
CHANGED
Binary file
|
data/lib/herb/3.1/herb.so
CHANGED
Binary file
|
data/lib/herb/3.2/herb.so
CHANGED
Binary file
|
data/lib/herb/3.3/herb.so
CHANGED
Binary file
|
data/lib/herb/3.4/herb.so
CHANGED
Binary file
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: true
|
3
|
+
|
4
|
+
module Herb
|
5
|
+
module AST
|
6
|
+
module Helpers
|
7
|
+
#: (Herb::AST::Node) -> bool
|
8
|
+
def erb_outputs?(node)
|
9
|
+
return false unless node.is_a?(Herb::AST::ERBContentNode)
|
10
|
+
|
11
|
+
opening = node.tag_opening&.value
|
12
|
+
opening&.include?("=") && !opening&.start_with?("<%#")
|
13
|
+
end
|
14
|
+
|
15
|
+
#: (String) -> bool
|
16
|
+
def erb_comment?(opening)
|
17
|
+
opening.start_with?("<%#")
|
18
|
+
end
|
19
|
+
|
20
|
+
#: (String) -> bool
|
21
|
+
def erb_output?(opening)
|
22
|
+
opening.include?("=")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/herb/ast/nodes.rb
CHANGED
@@ -269,15 +269,17 @@ module Herb
|
|
269
269
|
attr_reader :body #: Array[Herb::AST::Node]
|
270
270
|
attr_reader :close_tag #: Herb::AST::HTMLCloseTagNode
|
271
271
|
attr_reader :is_void #: bool
|
272
|
+
attr_reader :source #: String
|
272
273
|
|
273
|
-
#: (String, Location, Array[Herb::Errors::Error], Herb::AST::HTMLOpenTagNode, Herb::Token, Array[Herb::AST::Node], Herb::AST::HTMLCloseTagNode, bool) -> void
|
274
|
-
def initialize(type, location, errors, open_tag, tag_name, body, close_tag, is_void)
|
274
|
+
#: (String, Location, Array[Herb::Errors::Error], Herb::AST::HTMLOpenTagNode, Herb::Token, Array[Herb::AST::Node], Herb::AST::HTMLCloseTagNode, bool, String) -> void
|
275
|
+
def initialize(type, location, errors, open_tag, tag_name, body, close_tag, is_void, source)
|
275
276
|
super(type, location, errors)
|
276
277
|
@open_tag = open_tag
|
277
278
|
@tag_name = tag_name
|
278
279
|
@body = body
|
279
280
|
@close_tag = close_tag
|
280
281
|
@is_void = is_void
|
282
|
+
@source = source
|
281
283
|
end
|
282
284
|
|
283
285
|
#: () -> serialized_html_element_node
|
@@ -288,6 +290,7 @@ module Herb
|
|
288
290
|
body: body,
|
289
291
|
close_tag: close_tag,
|
290
292
|
is_void: is_void,
|
293
|
+
source: source,
|
291
294
|
}) #: Herb::serialized_html_element_node
|
292
295
|
end
|
293
296
|
|
@@ -342,9 +345,10 @@ module Herb
|
|
342
345
|
else
|
343
346
|
output += "∅\n"
|
344
347
|
end
|
345
|
-
output += "
|
348
|
+
output += "├── is_void: "
|
346
349
|
output += [true, false].include?(is_void) ? is_void.to_s : "∅"
|
347
350
|
output += "\n"
|
351
|
+
output += %(└── source: #{source.inspect}\n)
|
348
352
|
output += "\n"
|
349
353
|
|
350
354
|
output.gsub(/^/, " " * indent)
|
data/lib/herb/cli.rb
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
require "optparse"
|
7
7
|
|
8
8
|
class Herb::CLI
|
9
|
-
attr_accessor :json, :silent, :no_interactive, :no_log_file, :no_timing, :local
|
9
|
+
attr_accessor :json, :silent, :no_interactive, :no_log_file, :no_timing, :local, :escape, :no_escape, :freeze, :debug
|
10
10
|
|
11
11
|
def initialize(args)
|
12
12
|
@args = args
|
@@ -86,6 +86,8 @@ class Herb::CLI
|
|
86
86
|
Commands:
|
87
87
|
bundle exec herb lex [file] Lex a file.
|
88
88
|
bundle exec herb parse [file] Parse a file.
|
89
|
+
bundle exec herb compile [file] Compile ERB template to Ruby code.
|
90
|
+
bundle exec herb render [file] Compile and render ERB template to final output.
|
89
91
|
bundle exec herb analyze [path] Analyze a project by passing a directory to the root of the project
|
90
92
|
bundle exec herb ruby [file] Extract Ruby from a file.
|
91
93
|
bundle exec herb html [file] Extract HTML from a file.
|
@@ -110,10 +112,15 @@ class Herb::CLI
|
|
110
112
|
project.no_interactive = no_interactive
|
111
113
|
project.no_log_file = no_log_file
|
112
114
|
project.no_timing = no_timing
|
115
|
+
project.silent = silent
|
113
116
|
has_issues = project.parse!
|
114
117
|
exit(has_issues ? 1 : 0)
|
115
118
|
when "parse"
|
116
119
|
Herb.parse(file_content)
|
120
|
+
when "compile"
|
121
|
+
compile_template
|
122
|
+
when "render"
|
123
|
+
render_template
|
117
124
|
when "lex"
|
118
125
|
Herb.lex(file_content)
|
119
126
|
when "ruby"
|
@@ -191,6 +198,22 @@ class Herb::CLI
|
|
191
198
|
parser.on("--local", "Use localhost for playground command instead of herb-tools.dev") do
|
192
199
|
self.local = true
|
193
200
|
end
|
201
|
+
|
202
|
+
parser.on("--escape", "Enable HTML escaping by default (for compile command)") do
|
203
|
+
self.escape = true
|
204
|
+
end
|
205
|
+
|
206
|
+
parser.on("--no-escape", "Disable HTML escaping by default (for compile command)") do
|
207
|
+
self.no_escape = true
|
208
|
+
end
|
209
|
+
|
210
|
+
parser.on("--freeze", "Add frozen string literal pragma (for compile command)") do
|
211
|
+
self.freeze = true
|
212
|
+
end
|
213
|
+
|
214
|
+
parser.on("--debug", "Enable debug mode with ERB expression wrapping (for compile command)") do
|
215
|
+
self.debug = true
|
216
|
+
end
|
194
217
|
end
|
195
218
|
end
|
196
219
|
|
@@ -200,6 +223,140 @@ class Herb::CLI
|
|
200
223
|
|
201
224
|
private
|
202
225
|
|
226
|
+
def compile_template
|
227
|
+
require_relative "engine"
|
228
|
+
|
229
|
+
begin
|
230
|
+
options = {}
|
231
|
+
options[:filename] = @file if @file
|
232
|
+
options[:escape] = no_escape ? false : true
|
233
|
+
options[:freeze] = true if freeze
|
234
|
+
|
235
|
+
if debug
|
236
|
+
options[:debug] = true
|
237
|
+
options[:debug_filename] = @file if @file
|
238
|
+
end
|
239
|
+
|
240
|
+
engine = Herb::Engine.new(file_content, options)
|
241
|
+
|
242
|
+
if json
|
243
|
+
result = {
|
244
|
+
success: true,
|
245
|
+
source: engine.src,
|
246
|
+
filename: engine.filename,
|
247
|
+
bufvar: engine.bufvar,
|
248
|
+
}
|
249
|
+
|
250
|
+
puts result.to_json
|
251
|
+
elsif silent
|
252
|
+
puts "Success"
|
253
|
+
else
|
254
|
+
puts engine.src
|
255
|
+
end
|
256
|
+
|
257
|
+
exit(0)
|
258
|
+
rescue Herb::Engine::CompilationError => e
|
259
|
+
if json
|
260
|
+
result = {
|
261
|
+
success: false,
|
262
|
+
error: e.message,
|
263
|
+
filename: @file,
|
264
|
+
}
|
265
|
+
puts result.to_json
|
266
|
+
elsif silent
|
267
|
+
puts "Failed"
|
268
|
+
else
|
269
|
+
puts e.message
|
270
|
+
end
|
271
|
+
|
272
|
+
exit(1)
|
273
|
+
rescue StandardError => e
|
274
|
+
if json
|
275
|
+
result = {
|
276
|
+
success: false,
|
277
|
+
error: "Unexpected error: #{e.class}: #{e.message}",
|
278
|
+
filename: @file,
|
279
|
+
}
|
280
|
+
puts result.to_json
|
281
|
+
elsif silent
|
282
|
+
puts "Failed"
|
283
|
+
else
|
284
|
+
puts "Unexpected error: #{e.class}: #{e.message}"
|
285
|
+
puts e.backtrace.first(5).join("\n") unless silent
|
286
|
+
end
|
287
|
+
|
288
|
+
exit(1)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
def render_template
|
293
|
+
require_relative "engine"
|
294
|
+
|
295
|
+
begin
|
296
|
+
options = {}
|
297
|
+
options[:filename] = @file if @file
|
298
|
+
options[:escape] = no_escape ? false : true
|
299
|
+
options[:freeze] = true if freeze
|
300
|
+
|
301
|
+
if debug
|
302
|
+
options[:debug] = true
|
303
|
+
options[:debug_filename] = @file if @file
|
304
|
+
end
|
305
|
+
|
306
|
+
engine = Herb::Engine.new(file_content, options)
|
307
|
+
compiled_code = engine.src
|
308
|
+
|
309
|
+
rendered_output = eval(compiled_code)
|
310
|
+
|
311
|
+
if json
|
312
|
+
result = {
|
313
|
+
success: true,
|
314
|
+
output: rendered_output,
|
315
|
+
filename: engine.filename,
|
316
|
+
}
|
317
|
+
|
318
|
+
puts result.to_json
|
319
|
+
elsif silent
|
320
|
+
puts "Success"
|
321
|
+
else
|
322
|
+
puts rendered_output
|
323
|
+
end
|
324
|
+
|
325
|
+
exit(0)
|
326
|
+
rescue Herb::Engine::CompilationError => e
|
327
|
+
if json
|
328
|
+
result = {
|
329
|
+
success: false,
|
330
|
+
error: e.message,
|
331
|
+
filename: @file,
|
332
|
+
}
|
333
|
+
puts result.to_json
|
334
|
+
elsif silent
|
335
|
+
puts "Failed"
|
336
|
+
else
|
337
|
+
puts e.message
|
338
|
+
end
|
339
|
+
|
340
|
+
exit(1)
|
341
|
+
rescue StandardError => e
|
342
|
+
if json
|
343
|
+
result = {
|
344
|
+
success: false,
|
345
|
+
error: "Unexpected error: #{e.class}: #{e.message}",
|
346
|
+
filename: @file,
|
347
|
+
}
|
348
|
+
puts result.to_json
|
349
|
+
elsif silent
|
350
|
+
puts "Failed"
|
351
|
+
else
|
352
|
+
puts "Unexpected error: #{e.class}: #{e.message}"
|
353
|
+
puts e.backtrace.first(5).join("\n") unless silent
|
354
|
+
end
|
355
|
+
|
356
|
+
exit(1)
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
203
360
|
def print_version
|
204
361
|
puts Herb.version
|
205
362
|
exit(0)
|