herb 0.9.2-arm-linux-gnu → 0.9.4-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/README.md +2 -0
- data/config.yml +125 -0
- data/ext/herb/error_helpers.c +172 -2
- data/ext/herb/extconf.rb +6 -0
- data/ext/herb/extension.c +16 -2
- data/ext/herb/extension_helpers.c +6 -5
- data/ext/herb/extension_helpers.h +4 -4
- data/ext/herb/nodes.c +89 -3
- 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/erb_content_node.rb +32 -0
- data/lib/herb/ast/nodes.rb +244 -3
- data/lib/herb/cli.rb +12 -2
- data/lib/herb/engine/compiler.rb +166 -75
- data/lib/herb/engine/validators/security_validator.rb +40 -0
- data/lib/herb/engine.rb +3 -0
- data/lib/herb/errors.rb +268 -0
- data/lib/herb/parser_options.rb +7 -2
- data/lib/herb/project.rb +58 -17
- data/lib/herb/version.rb +1 -1
- data/lib/herb/visitor.rb +82 -0
- data/lib/herb.rb +1 -0
- data/sig/herb/ast/erb_content_node.rbs +13 -0
- data/sig/herb/ast/nodes.rbs +98 -2
- data/sig/herb/engine/compiler.rbs +31 -2
- data/sig/herb/engine/validators/security_validator.rbs +4 -0
- data/sig/herb/engine.rbs +3 -0
- data/sig/herb/errors.rbs +122 -0
- data/sig/herb/parser_options.rbs +6 -2
- data/sig/herb/visitor.rbs +12 -0
- data/sig/serialized_ast_errors.rbs +29 -0
- data/sig/serialized_ast_nodes.rbs +19 -0
- data/src/analyze/action_view/attribute_extraction_helpers.c +420 -91
- data/src/analyze/action_view/image_tag.c +87 -0
- data/src/analyze/action_view/javascript_include_tag.c +22 -12
- data/src/analyze/action_view/registry.c +6 -3
- data/src/analyze/action_view/tag.c +19 -2
- data/src/analyze/action_view/tag_helper_node_builders.c +105 -36
- data/src/analyze/action_view/tag_helpers.c +792 -44
- data/src/analyze/analyze.c +167 -13
- data/src/analyze/{helpers.c → analyze_helpers.c} +1 -1
- data/src/analyze/analyzed_ruby.c +1 -1
- data/src/analyze/builders.c +11 -8
- data/src/analyze/conditional_elements.c +6 -7
- data/src/analyze/conditional_open_tags.c +6 -7
- data/src/analyze/control_type.c +4 -2
- data/src/analyze/invalid_structures.c +5 -5
- data/src/analyze/missing_end.c +2 -2
- data/src/analyze/parse_errors.c +47 -6
- data/src/analyze/prism_annotate.c +7 -7
- data/src/analyze/render_nodes.c +6 -26
- data/src/analyze/strict_locals.c +651 -0
- data/src/analyze/transform.c +7 -0
- data/src/{ast_node.c → ast/ast_node.c} +8 -8
- data/src/{ast_nodes.c → ast/ast_nodes.c} +82 -11
- data/src/{ast_pretty_print.c → ast/ast_pretty_print.c} +113 -9
- data/src/{pretty_print.c → ast/pretty_print.c} +9 -9
- data/src/errors.c +398 -8
- data/src/extract.c +5 -5
- data/src/herb.c +15 -5
- data/src/include/analyze/action_view/attribute_extraction_helpers.h +3 -1
- data/src/include/analyze/action_view/tag_helper_handler.h +3 -3
- data/src/include/analyze/action_view/tag_helper_node_builders.h +34 -5
- data/src/include/analyze/action_view/tag_helpers.h +4 -3
- data/src/include/analyze/analyze.h +12 -5
- data/src/include/analyze/analyzed_ruby.h +2 -2
- data/src/include/analyze/builders.h +4 -4
- data/src/include/analyze/conditional_elements.h +2 -2
- data/src/include/analyze/conditional_open_tags.h +2 -2
- data/src/include/analyze/control_type.h +1 -1
- data/src/include/analyze/helpers.h +2 -2
- data/src/include/analyze/invalid_structures.h +1 -1
- data/src/include/analyze/prism_annotate.h +2 -2
- data/src/include/analyze/render_nodes.h +1 -1
- data/src/include/analyze/strict_locals.h +11 -0
- data/src/include/{ast_node.h → ast/ast_node.h} +4 -4
- data/src/include/{ast_nodes.h → ast/ast_nodes.h} +38 -14
- data/src/include/{ast_pretty_print.h → ast/ast_pretty_print.h} +3 -3
- data/src/include/{pretty_print.h → ast/pretty_print.h} +4 -4
- data/src/include/errors.h +65 -7
- data/src/include/extract.h +2 -2
- data/src/include/herb.h +5 -5
- data/src/include/{lex_helpers.h → lexer/lex_helpers.h} +5 -5
- data/src/include/{lexer.h → lexer/lexer.h} +1 -1
- data/src/include/{lexer_peek_helpers.h → lexer/lexer_peek_helpers.h} +2 -2
- data/src/include/{lexer_struct.h → lexer/lexer_struct.h} +2 -2
- data/src/include/{token.h → lexer/token.h} +3 -3
- data/src/include/{token_matchers.h → lexer/token_matchers.h} +1 -1
- data/src/include/{token_struct.h → lexer/token_struct.h} +3 -3
- data/src/include/{util → lib}/hb_foreach.h +1 -1
- data/src/include/{util → lib}/hb_string.h +5 -1
- data/src/include/{location.h → location/location.h} +1 -1
- data/src/include/parser/dot_notation.h +12 -0
- data/src/include/{parser.h → parser/parser.h} +11 -4
- data/src/include/{parser_helpers.h → parser/parser_helpers.h} +6 -6
- data/src/include/{prism_context.h → prism/prism_context.h} +2 -2
- data/src/include/{prism_helpers.h → prism/prism_helpers.h} +6 -6
- data/src/include/{html_util.h → util/html_util.h} +1 -1
- data/src/include/util/ruby_util.h +9 -0
- data/src/include/{utf8.h → util/utf8.h} +1 -1
- data/src/include/{util.h → util/util.h} +1 -1
- data/src/include/version.h +1 -1
- data/src/include/visitor.h +3 -3
- data/src/{lexer_peek_helpers.c → lexer/lexer_peek_helpers.c} +3 -3
- data/src/{token.c → lexer/token.c} +8 -8
- data/src/{token_matchers.c → lexer/token_matchers.c} +2 -2
- data/src/lexer.c +6 -6
- data/src/{util → lib}/hb_allocator.c +2 -2
- data/src/{util → lib}/hb_arena.c +1 -1
- data/src/{util → lib}/hb_arena_debug.c +2 -2
- data/src/{util → lib}/hb_array.c +2 -2
- data/src/{util → lib}/hb_buffer.c +2 -2
- data/src/{util → lib}/hb_narray.c +1 -1
- data/src/{util → lib}/hb_string.c +2 -2
- data/src/{location.c → location/location.c} +2 -2
- data/src/{position.c → location/position.c} +2 -2
- data/src/{range.c → location/range.c} +1 -1
- data/src/main.c +11 -11
- data/src/parser/dot_notation.c +100 -0
- data/src/{parser_match_tags.c → parser/match_tags.c} +34 -5
- data/src/{parser_helpers.c → parser/parser_helpers.c} +10 -10
- data/src/parser.c +68 -32
- data/src/{prism_helpers.c → prism/prism_helpers.c} +7 -7
- data/src/{ruby_parser.c → prism/ruby_parser.c} +1 -1
- data/src/{html_util.c → util/html_util.c} +4 -4
- data/src/{io.c → util/io.c} +3 -3
- data/src/util/ruby_util.c +42 -0
- data/src/{utf8.c → util/utf8.c} +2 -2
- data/src/{util.c → util/util.c} +4 -4
- data/src/visitor.c +35 -3
- data/templates/ext/herb/error_helpers.c.erb +2 -2
- data/templates/ext/herb/nodes.c.erb +1 -1
- data/templates/java/error_helpers.c.erb +1 -1
- data/templates/java/error_helpers.h.erb +2 -2
- data/templates/java/nodes.c.erb +4 -4
- data/templates/java/nodes.h.erb +1 -1
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +4 -4
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +4 -4
- data/templates/lib/herb/visitor.rb.erb +14 -0
- data/templates/src/analyze/missing_end.c.erb +2 -2
- data/templates/src/{ast_nodes.c.erb → ast/ast_nodes.c.erb} +9 -9
- data/templates/src/{ast_pretty_print.c.erb → ast/ast_pretty_print.c.erb} +8 -8
- data/templates/src/errors.c.erb +8 -8
- data/templates/src/include/{ast_nodes.h.erb → ast/ast_nodes.h.erb} +11 -12
- data/templates/src/include/{ast_pretty_print.h.erb → ast/ast_pretty_print.h.erb} +2 -2
- data/templates/src/include/errors.h.erb +7 -7
- data/templates/src/{parser_match_tags.c.erb → parser/match_tags.c.erb} +4 -4
- data/templates/src/visitor.c.erb +3 -3
- data/templates/wasm/error_helpers.cpp.erb +4 -4
- data/templates/wasm/nodes.cpp.erb +5 -5
- metadata +76 -68
- data/src/include/element_source.h +0 -10
- /data/src/include/{util → lib}/hb_allocator.h +0 -0
- /data/src/include/{util → lib}/hb_arena.h +0 -0
- /data/src/include/{util → lib}/hb_arena_debug.h +0 -0
- /data/src/include/{util → lib}/hb_array.h +0 -0
- /data/src/include/{util → lib}/hb_buffer.h +0 -0
- /data/src/include/{util → lib}/hb_narray.h +0 -0
- /data/src/include/{util → lib}/string.h +0 -0
- /data/src/include/{position.h → location/position.h} +0 -0
- /data/src/include/{range.h → location/range.h} +0 -0
- /data/src/include/{herb_prism_node.h → prism/herb_prism_node.h} +0 -0
- /data/src/include/{prism_serialized.h → prism/prism_serialized.h} +0 -0
- /data/src/include/{ruby_parser.h → prism/ruby_parser.h} +0 -0
- /data/src/include/{io.h → util/io.h} +0 -0
- /data/templates/src/include/{util → lib}/hb_foreach.h.erb +0 -0
|
@@ -140,4 +140,33 @@ module Herb
|
|
|
140
140
|
layout: String,
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
type serialized_strict_locals_positional_argument_error = serialized_error & {
|
|
144
|
+
name: String,
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
type serialized_strict_locals_block_argument_error = serialized_error & {
|
|
148
|
+
name: String,
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
type serialized_strict_locals_splat_argument_error = serialized_error & {
|
|
152
|
+
name: String,
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
type serialized_strict_locals_missing_parenthesis_error = serialized_error & {
|
|
156
|
+
rest: String,
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
type serialized_strict_locals_duplicate_declaration_error = serialized_error & {
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
type serialized_void_element_content_error = serialized_error & {
|
|
163
|
+
tag_name: Herb::Token,
|
|
164
|
+
helper_name: String,
|
|
165
|
+
content_type: String,
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
type serialized_dot_notation_casing_error = serialized_error & {
|
|
169
|
+
segment: Herb::Token,
|
|
170
|
+
}
|
|
171
|
+
|
|
143
172
|
end
|
|
@@ -170,6 +170,9 @@ module Herb
|
|
|
170
170
|
tag_closing: Herb::Token,
|
|
171
171
|
prism_node: String,
|
|
172
172
|
body: Array[Herb::AST::Node],
|
|
173
|
+
rescue_clause: Herb::AST::ERBRescueNode,
|
|
174
|
+
else_clause: Herb::AST::ERBElseNode,
|
|
175
|
+
ensure_clause: Herb::AST::ERBEnsureNode,
|
|
173
176
|
end_node: Herb::AST::ERBEndNode,
|
|
174
177
|
}
|
|
175
178
|
|
|
@@ -299,6 +302,22 @@ module Herb
|
|
|
299
302
|
locals: Array[Herb::AST::RubyRenderLocalNode],
|
|
300
303
|
}
|
|
301
304
|
|
|
305
|
+
type serialized_ruby_strict_local_node = serialized_node & {
|
|
306
|
+
name: Herb::Token,
|
|
307
|
+
default_value: Herb::AST::RubyLiteralNode,
|
|
308
|
+
required: bool,
|
|
309
|
+
double_splat: bool,
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
type serialized_erb_strict_locals_node = serialized_node & {
|
|
313
|
+
tag_opening: Herb::Token,
|
|
314
|
+
content: Herb::Token,
|
|
315
|
+
tag_closing: Herb::Token,
|
|
316
|
+
analyzed_ruby: nil,
|
|
317
|
+
prism_node: String,
|
|
318
|
+
locals: Array[Herb::AST::RubyStrictLocalNode],
|
|
319
|
+
}
|
|
320
|
+
|
|
302
321
|
type serialized_erb_yield_node = serialized_node & {
|
|
303
322
|
tag_opening: Herb::Token,
|
|
304
323
|
content: Herb::Token,
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#include "../../include/analyze/action_view/attribute_extraction_helpers.h"
|
|
2
2
|
#include "../../include/analyze/action_view/tag_helper_node_builders.h"
|
|
3
|
-
#include "../../include/
|
|
4
|
-
#include "../../include/
|
|
5
|
-
#include "../../include/
|
|
6
|
-
#include "../../include/
|
|
7
|
-
#include "../../include/util/
|
|
3
|
+
#include "../../include/lib/hb_allocator.h"
|
|
4
|
+
#include "../../include/lib/hb_array.h"
|
|
5
|
+
#include "../../include/lib/hb_buffer.h"
|
|
6
|
+
#include "../../include/lib/hb_string.h"
|
|
7
|
+
#include "../../include/util/html_util.h"
|
|
8
|
+
#include "../../include/util/util.h"
|
|
8
9
|
|
|
9
10
|
#include <prism.h>
|
|
10
11
|
#include <stdlib.h>
|
|
@@ -29,6 +30,171 @@ static char* extract_string_from_prism_node(pm_node_t* node, hb_allocator_T* all
|
|
|
29
30
|
return hb_allocator_strndup(allocator, (const char*) source, length);
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
static void compute_position_pair(
|
|
34
|
+
const pm_location_t* location,
|
|
35
|
+
const uint8_t* source,
|
|
36
|
+
const char* original_source,
|
|
37
|
+
size_t erb_content_offset,
|
|
38
|
+
position_T* out_start,
|
|
39
|
+
position_T* out_end
|
|
40
|
+
) {
|
|
41
|
+
*out_start = prism_location_to_position_with_offset(location, original_source, erb_content_offset, source);
|
|
42
|
+
pm_location_t end_location = { .start = location->end, .end = location->end };
|
|
43
|
+
*out_end = prism_location_to_position_with_offset(&end_location, original_source, erb_content_offset, source);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static void extract_key_name_location(pm_node_t* key, pm_location_t* out_name_loc) {
|
|
47
|
+
if (key->type == PM_SYMBOL_NODE) {
|
|
48
|
+
pm_symbol_node_t* symbol = (pm_symbol_node_t*) key;
|
|
49
|
+
*out_name_loc = symbol->value_loc;
|
|
50
|
+
} else if (key->type == PM_STRING_NODE) {
|
|
51
|
+
pm_string_node_t* string_node = (pm_string_node_t*) key;
|
|
52
|
+
*out_name_loc = string_node->content_loc;
|
|
53
|
+
} else {
|
|
54
|
+
*out_name_loc = key->location;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static void compute_separator_info(
|
|
59
|
+
pm_assoc_node_t* assoc,
|
|
60
|
+
const uint8_t* source,
|
|
61
|
+
const char* original_source,
|
|
62
|
+
size_t erb_content_offset,
|
|
63
|
+
position_T key_end,
|
|
64
|
+
const char** out_separator_string,
|
|
65
|
+
token_type_T* out_separator_type,
|
|
66
|
+
position_T* out_separator_start,
|
|
67
|
+
position_T* out_separator_end
|
|
68
|
+
) {
|
|
69
|
+
*out_separator_end =
|
|
70
|
+
prism_location_to_position_with_offset(&assoc->value->location, original_source, erb_content_offset, source);
|
|
71
|
+
|
|
72
|
+
if (assoc->operator_loc.start != NULL) {
|
|
73
|
+
*out_separator_string = " => ";
|
|
74
|
+
*out_separator_type = TOKEN_EQUALS;
|
|
75
|
+
*out_separator_start = key_end;
|
|
76
|
+
} else {
|
|
77
|
+
*out_separator_string = ": ";
|
|
78
|
+
*out_separator_type = TOKEN_COLON;
|
|
79
|
+
|
|
80
|
+
pm_location_t colon_loc = {
|
|
81
|
+
.start = assoc->key->location.end - 1,
|
|
82
|
+
.end = assoc->key->location.end - 1,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
*out_separator_start =
|
|
86
|
+
prism_location_to_position_with_offset(&colon_loc, original_source, erb_content_offset, source);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static void extract_delimited_locations(
|
|
91
|
+
pm_node_t* node,
|
|
92
|
+
const pm_location_t** out_opening,
|
|
93
|
+
const pm_location_t** out_closing,
|
|
94
|
+
const pm_location_t** out_content
|
|
95
|
+
) {
|
|
96
|
+
if (node->type == PM_STRING_NODE) {
|
|
97
|
+
pm_string_node_t* string_node = (pm_string_node_t*) node;
|
|
98
|
+
*out_opening = &string_node->opening_loc;
|
|
99
|
+
*out_closing = &string_node->closing_loc;
|
|
100
|
+
*out_content = &string_node->content_loc;
|
|
101
|
+
} else if (node->type == PM_SYMBOL_NODE) {
|
|
102
|
+
pm_symbol_node_t* symbol_node = (pm_symbol_node_t*) node;
|
|
103
|
+
*out_opening = &symbol_node->opening_loc;
|
|
104
|
+
*out_closing = &symbol_node->closing_loc;
|
|
105
|
+
*out_content = &symbol_node->value_loc;
|
|
106
|
+
} else {
|
|
107
|
+
*out_opening = NULL;
|
|
108
|
+
*out_closing = NULL;
|
|
109
|
+
*out_content = NULL;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
static void compute_value_positions(
|
|
114
|
+
pm_node_t* value_node,
|
|
115
|
+
const uint8_t* source,
|
|
116
|
+
const char* original_source,
|
|
117
|
+
size_t erb_content_offset,
|
|
118
|
+
position_T* out_value_start,
|
|
119
|
+
position_T* out_value_end,
|
|
120
|
+
position_T* out_content_start,
|
|
121
|
+
position_T* out_content_end,
|
|
122
|
+
bool* out_quoted
|
|
123
|
+
) {
|
|
124
|
+
const pm_location_t* opening_loc;
|
|
125
|
+
const pm_location_t* closing_loc;
|
|
126
|
+
const pm_location_t* content_loc;
|
|
127
|
+
|
|
128
|
+
extract_delimited_locations(value_node, &opening_loc, &closing_loc, &content_loc);
|
|
129
|
+
|
|
130
|
+
if (opening_loc && opening_loc->start != NULL && closing_loc && closing_loc->start != NULL) {
|
|
131
|
+
compute_position_pair(
|
|
132
|
+
&*opening_loc,
|
|
133
|
+
source,
|
|
134
|
+
original_source,
|
|
135
|
+
erb_content_offset,
|
|
136
|
+
out_value_start,
|
|
137
|
+
out_content_start
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
compute_position_pair(&*closing_loc, source, original_source, erb_content_offset, out_content_end, out_value_end);
|
|
141
|
+
*out_quoted = true;
|
|
142
|
+
} else {
|
|
143
|
+
const pm_location_t* fallback_loc = content_loc ? content_loc : &value_node->location;
|
|
144
|
+
compute_position_pair(fallback_loc, source, original_source, erb_content_offset, out_value_start, out_value_end);
|
|
145
|
+
*out_content_start = *out_value_start;
|
|
146
|
+
*out_content_end = *out_value_end;
|
|
147
|
+
*out_quoted = false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
static void fill_attribute_positions(
|
|
152
|
+
pm_assoc_node_t* assoc,
|
|
153
|
+
const uint8_t* source,
|
|
154
|
+
const char* original_source,
|
|
155
|
+
size_t erb_content_offset,
|
|
156
|
+
attribute_positions_T* positions
|
|
157
|
+
) {
|
|
158
|
+
pm_location_t name_loc;
|
|
159
|
+
extract_key_name_location(assoc->key, &name_loc);
|
|
160
|
+
compute_position_pair(
|
|
161
|
+
&name_loc,
|
|
162
|
+
source,
|
|
163
|
+
original_source,
|
|
164
|
+
erb_content_offset,
|
|
165
|
+
&positions->name_start,
|
|
166
|
+
&positions->name_end
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
position_T key_end;
|
|
170
|
+
pm_location_t key_end_loc = { .start = assoc->key->location.end, .end = assoc->key->location.end };
|
|
171
|
+
key_end = prism_location_to_position_with_offset(&key_end_loc, original_source, erb_content_offset, source);
|
|
172
|
+
|
|
173
|
+
compute_separator_info(
|
|
174
|
+
assoc,
|
|
175
|
+
source,
|
|
176
|
+
original_source,
|
|
177
|
+
erb_content_offset,
|
|
178
|
+
key_end,
|
|
179
|
+
&positions->separator_string,
|
|
180
|
+
&positions->separator_type,
|
|
181
|
+
&positions->separator_start,
|
|
182
|
+
&positions->separator_end
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
compute_value_positions(
|
|
186
|
+
assoc->value,
|
|
187
|
+
source,
|
|
188
|
+
original_source,
|
|
189
|
+
erb_content_offset,
|
|
190
|
+
&positions->value_start,
|
|
191
|
+
&positions->value_end,
|
|
192
|
+
&positions->content_start,
|
|
193
|
+
&positions->content_end,
|
|
194
|
+
&positions->quoted
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
32
198
|
static char* build_prefixed_key(const char* prefix, const char* raw_key, hb_allocator_T* allocator) {
|
|
33
199
|
char* dashed_key = convert_underscores_to_dashes(raw_key);
|
|
34
200
|
const char* key = dashed_key ? dashed_key : raw_key;
|
|
@@ -43,46 +209,125 @@ static char* build_prefixed_key(const char* prefix, const char* raw_key, hb_allo
|
|
|
43
209
|
return result;
|
|
44
210
|
}
|
|
45
211
|
|
|
212
|
+
static bool is_static_string_array(pm_array_node_t* array) {
|
|
213
|
+
if (!array || array->elements.size == 0) { return false; }
|
|
214
|
+
|
|
215
|
+
for (size_t i = 0; i < array->elements.size; i++) {
|
|
216
|
+
pm_node_t* element = array->elements.nodes[i];
|
|
217
|
+
|
|
218
|
+
if (element->type != PM_STRING_NODE && element->type != PM_SYMBOL_NODE) { return false; }
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
static char* join_static_string_array(pm_array_node_t* array, hb_allocator_T* allocator) {
|
|
225
|
+
hb_buffer_T buffer;
|
|
226
|
+
hb_buffer_init(&buffer, 64, allocator);
|
|
227
|
+
|
|
228
|
+
for (size_t i = 0; i < array->elements.size; i++) {
|
|
229
|
+
if (i > 0) { hb_buffer_append(&buffer, " "); }
|
|
230
|
+
|
|
231
|
+
char* value = extract_string_from_prism_node(array->elements.nodes[i], allocator);
|
|
232
|
+
|
|
233
|
+
if (value) {
|
|
234
|
+
hb_buffer_append(&buffer, value);
|
|
235
|
+
hb_allocator_dealloc(allocator, value);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
char* result = hb_allocator_strdup(allocator, hb_buffer_value(&buffer));
|
|
240
|
+
|
|
241
|
+
return result;
|
|
242
|
+
}
|
|
243
|
+
|
|
46
244
|
static AST_HTML_ATTRIBUTE_NODE_T* create_attribute_from_value(
|
|
47
245
|
const char* name_string,
|
|
48
246
|
pm_node_t* value_node,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
247
|
+
attribute_positions_T* positions,
|
|
248
|
+
hb_allocator_T* allocator,
|
|
249
|
+
bool is_nested
|
|
52
250
|
) {
|
|
251
|
+
if (value_node->type == PM_ARRAY_NODE && !is_nested && is_static_string_array((pm_array_node_t*) value_node)) {
|
|
252
|
+
char* joined = join_static_string_array((pm_array_node_t*) value_node, allocator);
|
|
253
|
+
if (!joined) { return NULL; }
|
|
254
|
+
|
|
255
|
+
AST_HTML_ATTRIBUTE_NODE_T* attribute =
|
|
256
|
+
create_html_attribute_node_precise(name_string, joined, positions, allocator);
|
|
257
|
+
hb_allocator_dealloc(allocator, joined);
|
|
258
|
+
|
|
259
|
+
return attribute;
|
|
260
|
+
}
|
|
261
|
+
|
|
53
262
|
if (value_node->type == PM_SYMBOL_NODE || value_node->type == PM_STRING_NODE) {
|
|
54
263
|
char* value_string = extract_string_from_prism_node(value_node, allocator);
|
|
55
264
|
if (!value_string) { return NULL; }
|
|
56
265
|
|
|
57
266
|
AST_HTML_ATTRIBUTE_NODE_T* attribute =
|
|
58
|
-
|
|
267
|
+
create_html_attribute_node_precise(name_string, value_string, positions, allocator);
|
|
59
268
|
hb_allocator_dealloc(allocator, value_string);
|
|
60
269
|
|
|
61
270
|
return attribute;
|
|
62
271
|
} else if (value_node->type == PM_TRUE_NODE) {
|
|
63
272
|
if (is_boolean_attribute(hb_string((char*) name_string))) {
|
|
64
|
-
return
|
|
273
|
+
return create_html_attribute_node_precise(name_string, NULL, positions, allocator);
|
|
65
274
|
}
|
|
66
|
-
|
|
275
|
+
|
|
276
|
+
return create_html_attribute_node_precise(name_string, "true", positions, allocator);
|
|
67
277
|
} else if (value_node->type == PM_FALSE_NODE) {
|
|
68
278
|
if (is_boolean_attribute(hb_string((char*) name_string))) { return NULL; }
|
|
69
|
-
|
|
279
|
+
|
|
280
|
+
return create_html_attribute_node_precise(name_string, "false", positions, allocator);
|
|
281
|
+
} else if (value_node->type == PM_INTEGER_NODE) {
|
|
282
|
+
size_t value_length = value_node->location.end - value_node->location.start;
|
|
283
|
+
char* value_string = hb_allocator_strndup(allocator, (const char*) value_node->location.start, value_length);
|
|
284
|
+
if (!value_string) { return NULL; }
|
|
285
|
+
|
|
286
|
+
AST_HTML_ATTRIBUTE_NODE_T* attribute =
|
|
287
|
+
create_html_attribute_node_precise(name_string, value_string, positions, allocator);
|
|
288
|
+
hb_allocator_dealloc(allocator, value_string);
|
|
289
|
+
|
|
290
|
+
return attribute;
|
|
70
291
|
} else if (value_node->type == PM_INTERPOLATED_STRING_NODE) {
|
|
71
292
|
return create_html_attribute_with_interpolated_value(
|
|
72
293
|
name_string,
|
|
73
294
|
(pm_interpolated_string_node_t*) value_node,
|
|
74
|
-
|
|
75
|
-
|
|
295
|
+
positions->name_start,
|
|
296
|
+
positions->value_end,
|
|
76
297
|
allocator
|
|
77
298
|
);
|
|
78
299
|
} else {
|
|
79
300
|
size_t value_length = value_node->location.end - value_node->location.start;
|
|
80
|
-
char*
|
|
301
|
+
char* raw_content = hb_allocator_strndup(allocator, (const char*) value_node->location.start, value_length);
|
|
302
|
+
|
|
303
|
+
if (raw_content && value_node->location.start) {
|
|
304
|
+
char* ruby_content = raw_content;
|
|
305
|
+
|
|
306
|
+
if (!is_nested && strcmp(name_string, "class") == 0
|
|
307
|
+
&& (value_node->type == PM_HASH_NODE || value_node->type == PM_ARRAY_NODE)) {
|
|
308
|
+
hb_buffer_T class_buffer;
|
|
309
|
+
hb_buffer_init(&class_buffer, value_length + 16, allocator);
|
|
310
|
+
hb_buffer_append(&class_buffer, "token_list(");
|
|
311
|
+
hb_buffer_append(&class_buffer, raw_content);
|
|
312
|
+
hb_buffer_append(&class_buffer, ")");
|
|
313
|
+
|
|
314
|
+
ruby_content = hb_buffer_value(&class_buffer);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Rails calls .to_json on non-string/symbol values inside data:/aria: hashes
|
|
318
|
+
if (is_nested) {
|
|
319
|
+
hb_buffer_T json_buffer;
|
|
320
|
+
hb_buffer_init(&json_buffer, value_length + 16, allocator);
|
|
321
|
+
hb_buffer_append(&json_buffer, raw_content);
|
|
322
|
+
hb_buffer_append(&json_buffer, ".to_json");
|
|
323
|
+
|
|
324
|
+
ruby_content = hb_buffer_value(&json_buffer);
|
|
325
|
+
}
|
|
81
326
|
|
|
82
|
-
if (ruby_content && value_node->location.start) {
|
|
83
327
|
AST_HTML_ATTRIBUTE_NODE_T* attribute =
|
|
84
|
-
|
|
85
|
-
hb_allocator_dealloc(allocator,
|
|
328
|
+
create_html_attribute_with_ruby_literal_precise(name_string, ruby_content, positions, allocator);
|
|
329
|
+
hb_allocator_dealloc(allocator, raw_content);
|
|
330
|
+
|
|
86
331
|
return attribute;
|
|
87
332
|
}
|
|
88
333
|
|
|
@@ -90,6 +335,58 @@ static AST_HTML_ATTRIBUTE_NODE_T* create_attribute_from_value(
|
|
|
90
335
|
}
|
|
91
336
|
}
|
|
92
337
|
|
|
338
|
+
static const char* get_attribute_name_string(AST_HTML_ATTRIBUTE_NODE_T* attribute) {
|
|
339
|
+
if (!attribute || !attribute->name || !attribute->name->children) { return NULL; }
|
|
340
|
+
if (hb_array_size(attribute->name->children) == 0) { return NULL; }
|
|
341
|
+
|
|
342
|
+
AST_NODE_T* first_child = (AST_NODE_T*) hb_array_get(attribute->name->children, 0);
|
|
343
|
+
if (!first_child || first_child->type != AST_LITERAL_NODE) { return NULL; }
|
|
344
|
+
|
|
345
|
+
AST_LITERAL_NODE_T* literal = (AST_LITERAL_NODE_T*) first_child;
|
|
346
|
+
return (const char*) literal->content.data;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
void resolve_nonce_attribute(hb_array_T* attributes, hb_allocator_T* allocator) {
|
|
350
|
+
if (!attributes) { return; }
|
|
351
|
+
|
|
352
|
+
for (size_t index = 0; index < hb_array_size(attributes); index++) {
|
|
353
|
+
AST_NODE_T* node = hb_array_get(attributes, index);
|
|
354
|
+
if (!node || node->type != AST_HTML_ATTRIBUTE_NODE) { continue; }
|
|
355
|
+
|
|
356
|
+
AST_HTML_ATTRIBUTE_NODE_T* attribute = (AST_HTML_ATTRIBUTE_NODE_T*) node;
|
|
357
|
+
const char* name = get_attribute_name_string(attribute);
|
|
358
|
+
if (!name || strcmp(name, "nonce") != 0) { continue; }
|
|
359
|
+
|
|
360
|
+
if (!attribute->value || !attribute->value->children) { continue; }
|
|
361
|
+
if (hb_array_size(attribute->value->children) == 0) { continue; }
|
|
362
|
+
|
|
363
|
+
AST_NODE_T* value_child = (AST_NODE_T*) hb_array_get(attribute->value->children, 0);
|
|
364
|
+
if (!value_child || value_child->type != AST_LITERAL_NODE) { continue; }
|
|
365
|
+
|
|
366
|
+
AST_LITERAL_NODE_T* literal = (AST_LITERAL_NODE_T*) value_child;
|
|
367
|
+
|
|
368
|
+
if (hb_string_equals(literal->content, hb_string("true"))) {
|
|
369
|
+
AST_RUBY_LITERAL_NODE_T* ruby_node = ast_ruby_literal_node_init(
|
|
370
|
+
hb_string_from_c_string("content_security_policy_nonce"),
|
|
371
|
+
attribute->value->base.location.start,
|
|
372
|
+
attribute->value->base.location.end,
|
|
373
|
+
hb_array_init(0, allocator),
|
|
374
|
+
allocator
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
hb_array_T* new_children = hb_array_init(1, allocator);
|
|
378
|
+
hb_array_append(new_children, (AST_NODE_T*) ruby_node);
|
|
379
|
+
attribute->value->children = new_children;
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (hb_string_equals(literal->content, hb_string("false"))) {
|
|
384
|
+
hb_array_remove(attributes, index);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
93
390
|
AST_HTML_ATTRIBUTE_NODE_T* extract_html_attribute_from_assoc(
|
|
94
391
|
pm_assoc_node_t* assoc,
|
|
95
392
|
const uint8_t* source,
|
|
@@ -102,10 +399,37 @@ AST_HTML_ATTRIBUTE_NODE_T* extract_html_attribute_from_assoc(
|
|
|
102
399
|
char* name_string = extract_string_from_prism_node(assoc->key, allocator);
|
|
103
400
|
if (!name_string) { return NULL; }
|
|
104
401
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
402
|
+
if (strcmp(name_string, "escape") == 0) {
|
|
403
|
+
hb_allocator_dealloc(allocator, name_string);
|
|
404
|
+
return NULL;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (!assoc->value) {
|
|
408
|
+
hb_allocator_dealloc(allocator, name_string);
|
|
409
|
+
return NULL;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (assoc->value->type == PM_IMPLICIT_NODE) {
|
|
413
|
+
pm_location_t name_loc;
|
|
414
|
+
extract_key_name_location(assoc->key, &name_loc);
|
|
415
|
+
position_T name_start, name_end;
|
|
416
|
+
compute_position_pair(&name_loc, source, original_source, erb_content_offset, &name_start, &name_end);
|
|
417
|
+
|
|
418
|
+
char* dashed_name = convert_underscores_to_dashes(name_string);
|
|
419
|
+
|
|
420
|
+
AST_HTML_ATTRIBUTE_NODE_T* attribute = create_html_attribute_with_ruby_literal(
|
|
421
|
+
dashed_name ? dashed_name : name_string,
|
|
422
|
+
name_string,
|
|
423
|
+
name_start,
|
|
424
|
+
name_start,
|
|
425
|
+
allocator
|
|
426
|
+
);
|
|
427
|
+
|
|
428
|
+
if (dashed_name) { free(dashed_name); }
|
|
429
|
+
hb_allocator_dealloc(allocator, name_string);
|
|
430
|
+
|
|
431
|
+
return attribute;
|
|
432
|
+
}
|
|
109
433
|
|
|
110
434
|
// Rails converts `method:` and `remote:` to `data-*` attributes
|
|
111
435
|
if (strcmp(name_string, "method") == 0 || strcmp(name_string, "remote") == 0) {
|
|
@@ -122,14 +446,12 @@ AST_HTML_ATTRIBUTE_NODE_T* extract_html_attribute_from_assoc(
|
|
|
122
446
|
return NULL;
|
|
123
447
|
}
|
|
124
448
|
|
|
449
|
+
attribute_positions_T positions;
|
|
450
|
+
fill_attribute_positions(assoc, source, original_source, erb_content_offset, &positions);
|
|
451
|
+
|
|
125
452
|
char* dashed_name = convert_underscores_to_dashes(name_string);
|
|
126
|
-
AST_HTML_ATTRIBUTE_NODE_T* attribute_node =
|
|
127
|
-
dashed_name ? dashed_name : name_string,
|
|
128
|
-
assoc->value,
|
|
129
|
-
start_position,
|
|
130
|
-
end_position,
|
|
131
|
-
allocator
|
|
132
|
-
);
|
|
453
|
+
AST_HTML_ATTRIBUTE_NODE_T* attribute_node =
|
|
454
|
+
create_attribute_from_value(dashed_name ? dashed_name : name_string, assoc->value, &positions, allocator, false);
|
|
133
455
|
|
|
134
456
|
if (dashed_name) { free(dashed_name); }
|
|
135
457
|
hb_allocator_dealloc(allocator, name_string);
|
|
@@ -154,25 +476,35 @@ hb_array_T* extract_html_attributes_from_keyword_hash(
|
|
|
154
476
|
|
|
155
477
|
if (element->type == PM_ASSOC_SPLAT_NODE) {
|
|
156
478
|
pm_assoc_splat_node_t* splat = (pm_assoc_splat_node_t*) element;
|
|
157
|
-
size_t splat_length = splat->base.location.end - splat->base.location.start;
|
|
158
|
-
char* splat_content = hb_allocator_strndup(allocator, (const char*) splat->base.location.start, splat_length);
|
|
159
|
-
|
|
160
|
-
if (splat_content) {
|
|
161
|
-
position_T splat_start =
|
|
162
|
-
prism_location_to_position_with_offset(&splat->base.location, original_source, erb_content_offset, source);
|
|
163
|
-
|
|
164
|
-
AST_RUBY_HTML_ATTRIBUTES_SPLAT_NODE_T* splat_node = ast_ruby_html_attributes_splat_node_init(
|
|
165
|
-
hb_string_from_c_string(splat_content),
|
|
166
|
-
HB_STRING_EMPTY,
|
|
167
|
-
splat_start,
|
|
168
|
-
splat_start,
|
|
169
|
-
hb_array_init(0, allocator),
|
|
170
|
-
allocator
|
|
171
|
-
);
|
|
172
479
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
480
|
+
if (splat->value) {
|
|
481
|
+
size_t value_length = splat->value->location.end - splat->value->location.start;
|
|
482
|
+
char* value_source = hb_allocator_strndup(allocator, (const char*) splat->value->location.start, value_length);
|
|
483
|
+
|
|
484
|
+
if (value_source) {
|
|
485
|
+
hb_buffer_T wrapped;
|
|
486
|
+
hb_buffer_init(&wrapped, value_length + 32, allocator);
|
|
487
|
+
hb_buffer_append(&wrapped, "tag.attributes(**");
|
|
488
|
+
hb_buffer_append(&wrapped, value_source);
|
|
489
|
+
hb_buffer_append(&wrapped, ")");
|
|
490
|
+
|
|
491
|
+
position_T splat_start =
|
|
492
|
+
prism_location_to_position_with_offset(&splat->base.location, original_source, erb_content_offset, source);
|
|
493
|
+
|
|
494
|
+
AST_RUBY_HTML_ATTRIBUTES_SPLAT_NODE_T* splat_node = ast_ruby_html_attributes_splat_node_init(
|
|
495
|
+
hb_string_from_c_string(hb_buffer_value(&wrapped)),
|
|
496
|
+
HB_STRING_EMPTY,
|
|
497
|
+
splat_start,
|
|
498
|
+
splat_start,
|
|
499
|
+
hb_array_init(0, allocator),
|
|
500
|
+
allocator
|
|
501
|
+
);
|
|
502
|
+
|
|
503
|
+
if (splat_node) { hb_array_append(attributes, (AST_NODE_T*) splat_node); }
|
|
504
|
+
|
|
505
|
+
hb_buffer_free(&wrapped);
|
|
506
|
+
hb_allocator_dealloc(allocator, value_source);
|
|
507
|
+
}
|
|
176
508
|
}
|
|
177
509
|
} else if (element->type == PM_ASSOC_NODE) {
|
|
178
510
|
pm_assoc_node_t* assoc = (pm_assoc_node_t*) element;
|
|
@@ -188,30 +520,42 @@ hb_array_T* extract_html_attributes_from_keyword_hash(
|
|
|
188
520
|
|
|
189
521
|
if (hash_element->type == PM_ASSOC_SPLAT_NODE) {
|
|
190
522
|
pm_assoc_splat_node_t* splat = (pm_assoc_splat_node_t*) hash_element;
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
splat_start
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
523
|
+
|
|
524
|
+
if (splat->value) {
|
|
525
|
+
size_t value_length = splat->value->location.end - splat->value->location.start;
|
|
526
|
+
char* value_source =
|
|
527
|
+
hb_allocator_strndup(allocator, (const char*) splat->value->location.start, value_length);
|
|
528
|
+
|
|
529
|
+
if (value_source) {
|
|
530
|
+
hb_buffer_T wrapped;
|
|
531
|
+
hb_buffer_init(&wrapped, value_length + 48, allocator);
|
|
532
|
+
hb_buffer_append(&wrapped, "tag.attributes(");
|
|
533
|
+
hb_buffer_append(&wrapped, key_string);
|
|
534
|
+
hb_buffer_append(&wrapped, ": ");
|
|
535
|
+
hb_buffer_append(&wrapped, value_source);
|
|
536
|
+
hb_buffer_append(&wrapped, ")");
|
|
537
|
+
|
|
538
|
+
position_T splat_start = prism_location_to_position_with_offset(
|
|
539
|
+
&splat->base.location,
|
|
540
|
+
original_source,
|
|
541
|
+
erb_content_offset,
|
|
542
|
+
source
|
|
543
|
+
);
|
|
544
|
+
|
|
545
|
+
AST_RUBY_HTML_ATTRIBUTES_SPLAT_NODE_T* splat_node = ast_ruby_html_attributes_splat_node_init(
|
|
546
|
+
hb_string_from_c_string(hb_buffer_value(&wrapped)),
|
|
547
|
+
hb_string_from_c_string(key_string),
|
|
548
|
+
splat_start,
|
|
549
|
+
splat_start,
|
|
550
|
+
hb_array_init(0, allocator),
|
|
551
|
+
allocator
|
|
552
|
+
);
|
|
553
|
+
|
|
554
|
+
if (splat_node) { hb_array_append(attributes, (AST_NODE_T*) splat_node); }
|
|
555
|
+
|
|
556
|
+
hb_buffer_free(&wrapped);
|
|
557
|
+
hb_allocator_dealloc(allocator, value_source);
|
|
558
|
+
}
|
|
215
559
|
}
|
|
216
560
|
|
|
217
561
|
continue;
|
|
@@ -227,26 +571,11 @@ hb_array_T* extract_html_attributes_from_keyword_hash(
|
|
|
227
571
|
hb_allocator_dealloc(allocator, raw_key);
|
|
228
572
|
|
|
229
573
|
if (attribute_key_string) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
);
|
|
236
|
-
position_T attribute_end = prism_location_to_position_with_offset(
|
|
237
|
-
&hash_assoc->value->location,
|
|
238
|
-
original_source,
|
|
239
|
-
erb_content_offset,
|
|
240
|
-
source
|
|
241
|
-
);
|
|
242
|
-
|
|
243
|
-
AST_HTML_ATTRIBUTE_NODE_T* attribute = create_attribute_from_value(
|
|
244
|
-
attribute_key_string,
|
|
245
|
-
hash_assoc->value,
|
|
246
|
-
attribute_start,
|
|
247
|
-
attribute_end,
|
|
248
|
-
allocator
|
|
249
|
-
);
|
|
574
|
+
attribute_positions_T hash_positions;
|
|
575
|
+
fill_attribute_positions(hash_assoc, source, original_source, erb_content_offset, &hash_positions);
|
|
576
|
+
|
|
577
|
+
AST_HTML_ATTRIBUTE_NODE_T* attribute =
|
|
578
|
+
create_attribute_from_value(attribute_key_string, hash_assoc->value, &hash_positions, allocator, true);
|
|
250
579
|
|
|
251
580
|
if (attribute) { hb_array_append(attributes, attribute); }
|
|
252
581
|
hb_allocator_dealloc(allocator, attribute_key_string);
|