herb 0.9.2 → 0.9.4
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/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
|
@@ -3,13 +3,17 @@
|
|
|
3
3
|
#include "../../include/analyze/action_view/tag_helper_handler.h"
|
|
4
4
|
#include "../../include/analyze/action_view/tag_helper_node_builders.h"
|
|
5
5
|
#include "../../include/analyze/analyze.h"
|
|
6
|
-
#include "../../include/ast_nodes.h"
|
|
7
|
-
#include "../../include/
|
|
8
|
-
#include "../../include/
|
|
9
|
-
#include "../../include/
|
|
10
|
-
#include "../../include/
|
|
11
|
-
#include "../../include/
|
|
12
|
-
#include "../../include/
|
|
6
|
+
#include "../../include/ast/ast_nodes.h"
|
|
7
|
+
#include "../../include/herb.h"
|
|
8
|
+
#include "../../include/lib/hb_allocator.h"
|
|
9
|
+
#include "../../include/lib/hb_array.h"
|
|
10
|
+
#include "../../include/lib/hb_buffer.h"
|
|
11
|
+
#include "../../include/lib/hb_string.h"
|
|
12
|
+
#include "../../include/lib/string.h"
|
|
13
|
+
#include "../../include/location/position.h"
|
|
14
|
+
#include "../../include/parser/parser_helpers.h"
|
|
15
|
+
#include "../../include/util/html_util.h"
|
|
16
|
+
#include "../../include/util/util.h"
|
|
13
17
|
#include "../../include/visitor.h"
|
|
14
18
|
|
|
15
19
|
#include <prism.h>
|
|
@@ -25,8 +29,12 @@ extern bool detect_turbo_frame_tag(pm_call_node_t*, pm_parser_t*);
|
|
|
25
29
|
extern char* extract_turbo_frame_tag_id(pm_call_node_t*, pm_parser_t*, hb_allocator_T*);
|
|
26
30
|
extern bool detect_javascript_include_tag(pm_call_node_t*, pm_parser_t*);
|
|
27
31
|
extern char* extract_javascript_include_tag_src(pm_call_node_t*, pm_parser_t*, hb_allocator_T*);
|
|
28
|
-
extern char* wrap_in_javascript_path(const char*, size_t, hb_allocator_T*);
|
|
32
|
+
extern char* wrap_in_javascript_path(const char*, size_t, const char*, hb_allocator_T*);
|
|
29
33
|
extern bool javascript_include_tag_source_is_url(const char*, size_t);
|
|
34
|
+
extern bool detect_image_tag(pm_call_node_t*, pm_parser_t*);
|
|
35
|
+
extern char* extract_image_tag_src(pm_call_node_t*, pm_parser_t*, hb_allocator_T*);
|
|
36
|
+
extern char* wrap_in_image_path(const char*, size_t, const char*, hb_allocator_T*);
|
|
37
|
+
extern bool image_tag_source_is_url(const char*, size_t);
|
|
30
38
|
|
|
31
39
|
typedef struct {
|
|
32
40
|
pm_parser_t parser;
|
|
@@ -37,6 +45,8 @@ typedef struct {
|
|
|
37
45
|
const tag_helper_handler_T* matched_handler;
|
|
38
46
|
const char* original_source;
|
|
39
47
|
size_t erb_content_offset;
|
|
48
|
+
char* condition_source;
|
|
49
|
+
char* condition_type;
|
|
40
50
|
} tag_helper_parse_context_T;
|
|
41
51
|
|
|
42
52
|
static tag_helper_parse_context_T* parse_tag_helper_content(
|
|
@@ -66,11 +76,15 @@ static tag_helper_parse_context_T* parse_tag_helper_content(
|
|
|
66
76
|
}
|
|
67
77
|
|
|
68
78
|
parse_context->info = tag_helper_info_init(allocator);
|
|
79
|
+
parse_context->condition_source = NULL;
|
|
80
|
+
parse_context->condition_type = NULL;
|
|
81
|
+
|
|
69
82
|
tag_helper_search_data_T search = { .tag_helper_node = NULL,
|
|
70
83
|
.source = parse_context->prism_source,
|
|
71
84
|
.parser = &parse_context->parser,
|
|
72
85
|
.info = parse_context->info,
|
|
73
|
-
.found = false
|
|
86
|
+
.found = false,
|
|
87
|
+
.postfix_conditional_node = NULL };
|
|
74
88
|
pm_visit_node(parse_context->root, search_tag_helper_node, &search);
|
|
75
89
|
|
|
76
90
|
if (!search.found) {
|
|
@@ -82,6 +96,22 @@ static tag_helper_parse_context_T* parse_tag_helper_content(
|
|
|
82
96
|
return NULL;
|
|
83
97
|
}
|
|
84
98
|
|
|
99
|
+
if (search.postfix_conditional_node) {
|
|
100
|
+
if (search.postfix_conditional_node->type == PM_IF_NODE) {
|
|
101
|
+
pm_if_node_t* if_node = (pm_if_node_t*) search.postfix_conditional_node;
|
|
102
|
+
size_t predicate_length = if_node->predicate->location.end - if_node->predicate->location.start;
|
|
103
|
+
parse_context->condition_source =
|
|
104
|
+
hb_allocator_strndup(allocator, (const char*) if_node->predicate->location.start, predicate_length);
|
|
105
|
+
parse_context->condition_type = hb_allocator_strdup(allocator, "if");
|
|
106
|
+
} else if (search.postfix_conditional_node->type == PM_UNLESS_NODE) {
|
|
107
|
+
pm_unless_node_t* unless_node = (pm_unless_node_t*) search.postfix_conditional_node;
|
|
108
|
+
size_t predicate_length = unless_node->predicate->location.end - unless_node->predicate->location.start;
|
|
109
|
+
parse_context->condition_source =
|
|
110
|
+
hb_allocator_strndup(allocator, (const char*) unless_node->predicate->location.start, predicate_length);
|
|
111
|
+
parse_context->condition_type = hb_allocator_strdup(allocator, "unless");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
85
115
|
parse_context->matched_handler = search.matched_handler;
|
|
86
116
|
return parse_context;
|
|
87
117
|
}
|
|
@@ -101,6 +131,92 @@ static void free_tag_helper_parse_context(tag_helper_parse_context_T* parse_cont
|
|
|
101
131
|
}
|
|
102
132
|
}
|
|
103
133
|
|
|
134
|
+
static AST_NODE_T* wrap_in_conditional_if_needed(
|
|
135
|
+
AST_NODE_T* element,
|
|
136
|
+
tag_helper_parse_context_T* parse_context,
|
|
137
|
+
hb_allocator_T* allocator
|
|
138
|
+
) {
|
|
139
|
+
if (!element || !parse_context || !parse_context->condition_source || !parse_context->condition_type) {
|
|
140
|
+
return element;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
position_T start = element->location.start;
|
|
144
|
+
position_T end = element->location.end;
|
|
145
|
+
|
|
146
|
+
hb_buffer_T content_buffer;
|
|
147
|
+
hb_buffer_init(&content_buffer, 64, allocator);
|
|
148
|
+
hb_buffer_append(&content_buffer, " ");
|
|
149
|
+
hb_buffer_append(&content_buffer, parse_context->condition_type);
|
|
150
|
+
hb_buffer_append(&content_buffer, " ");
|
|
151
|
+
hb_buffer_append(&content_buffer, parse_context->condition_source);
|
|
152
|
+
hb_buffer_append(&content_buffer, " ");
|
|
153
|
+
const char* content_string = hb_buffer_value(&content_buffer);
|
|
154
|
+
|
|
155
|
+
token_T* tag_opening = create_synthetic_token(allocator, "<%", TOKEN_ERB_START, start, start);
|
|
156
|
+
token_T* content_token = create_synthetic_token(allocator, content_string, TOKEN_ERB_CONTENT, start, end);
|
|
157
|
+
token_T* tag_closing = create_synthetic_token(allocator, "%>", TOKEN_ERB_END, end, end);
|
|
158
|
+
|
|
159
|
+
hb_array_T* statements = hb_array_init(1, allocator);
|
|
160
|
+
hb_array_append(statements, element);
|
|
161
|
+
|
|
162
|
+
token_T* end_opening = create_synthetic_token(allocator, "<%", TOKEN_ERB_START, end, end);
|
|
163
|
+
token_T* end_content = create_synthetic_token(allocator, " end ", TOKEN_ERB_CONTENT, end, end);
|
|
164
|
+
token_T* end_closing = create_synthetic_token(allocator, "%>", TOKEN_ERB_END, end, end);
|
|
165
|
+
|
|
166
|
+
AST_ERB_END_NODE_T* end_node =
|
|
167
|
+
ast_erb_end_node_init(end_opening, end_content, end_closing, end, end, hb_array_init(0, allocator), allocator);
|
|
168
|
+
|
|
169
|
+
herb_prism_node_T empty_prism_node = HERB_PRISM_NODE_EMPTY;
|
|
170
|
+
|
|
171
|
+
if (strcmp(parse_context->condition_type, "if") == 0) {
|
|
172
|
+
AST_ERB_IF_NODE_T* if_node = ast_erb_if_node_init(
|
|
173
|
+
tag_opening,
|
|
174
|
+
content_token,
|
|
175
|
+
tag_closing,
|
|
176
|
+
NULL,
|
|
177
|
+
empty_prism_node,
|
|
178
|
+
statements,
|
|
179
|
+
NULL,
|
|
180
|
+
end_node,
|
|
181
|
+
start,
|
|
182
|
+
end,
|
|
183
|
+
hb_array_init(0, allocator),
|
|
184
|
+
allocator
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
return (AST_NODE_T*) if_node;
|
|
188
|
+
} else {
|
|
189
|
+
AST_ERB_UNLESS_NODE_T* unless_node = ast_erb_unless_node_init(
|
|
190
|
+
tag_opening,
|
|
191
|
+
content_token,
|
|
192
|
+
tag_closing,
|
|
193
|
+
NULL,
|
|
194
|
+
empty_prism_node,
|
|
195
|
+
statements,
|
|
196
|
+
NULL,
|
|
197
|
+
end_node,
|
|
198
|
+
start,
|
|
199
|
+
end,
|
|
200
|
+
hb_array_init(0, allocator),
|
|
201
|
+
allocator
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
return (AST_NODE_T*) unless_node;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
static bool is_postfix_if_node(const pm_node_t* node) {
|
|
209
|
+
if (node->type != PM_IF_NODE) { return false; }
|
|
210
|
+
pm_if_node_t* if_node = (pm_if_node_t*) node;
|
|
211
|
+
return if_node->if_keyword_loc.start != NULL && if_node->end_keyword_loc.start == NULL;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
static bool is_postfix_unless_node(const pm_node_t* node) {
|
|
215
|
+
if (node->type != PM_UNLESS_NODE) { return false; }
|
|
216
|
+
pm_unless_node_t* unless_node = (pm_unless_node_t*) node;
|
|
217
|
+
return unless_node->keyword_loc.start != NULL && unless_node->end_keyword_loc.start == NULL;
|
|
218
|
+
}
|
|
219
|
+
|
|
104
220
|
bool search_tag_helper_node(const pm_node_t* node, void* data) {
|
|
105
221
|
tag_helper_search_data_T* search_data = (tag_helper_search_data_T*) data;
|
|
106
222
|
|
|
@@ -124,9 +240,21 @@ bool search_tag_helper_node(const pm_node_t* node, void* data) {
|
|
|
124
240
|
search_data->info->has_block = handlers[i].supports_block();
|
|
125
241
|
}
|
|
126
242
|
|
|
127
|
-
return
|
|
243
|
+
return false;
|
|
128
244
|
}
|
|
129
245
|
}
|
|
246
|
+
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (is_postfix_if_node(node) || is_postfix_unless_node(node)) {
|
|
251
|
+
const pm_node_t* saved = search_data->postfix_conditional_node;
|
|
252
|
+
search_data->postfix_conditional_node = node;
|
|
253
|
+
pm_visit_child_nodes(node, search_tag_helper_node, search_data);
|
|
254
|
+
|
|
255
|
+
if (!search_data->found) { search_data->postfix_conditional_node = saved; }
|
|
256
|
+
|
|
257
|
+
return search_data->found;
|
|
130
258
|
}
|
|
131
259
|
|
|
132
260
|
pm_visit_child_nodes(node, search_tag_helper_node, search_data);
|
|
@@ -230,6 +358,98 @@ static void calculate_tag_name_positions(
|
|
|
230
358
|
}
|
|
231
359
|
}
|
|
232
360
|
|
|
361
|
+
static const char* JAVASCRIPT_INCLUDE_TAG_PATH_OPTIONS[] = { "protocol", "extname", "host", "skip_pipeline", NULL };
|
|
362
|
+
static const char* IMAGE_TAG_PATH_OPTIONS[] = { "skip_pipeline", NULL };
|
|
363
|
+
|
|
364
|
+
static char* extract_path_options_from_keyword_hash(
|
|
365
|
+
pm_call_node_t* call_node,
|
|
366
|
+
const char** option_names,
|
|
367
|
+
hb_allocator_T* allocator
|
|
368
|
+
) {
|
|
369
|
+
if (!call_node || !call_node->arguments) { return NULL; }
|
|
370
|
+
|
|
371
|
+
pm_arguments_node_t* arguments = call_node->arguments;
|
|
372
|
+
if (arguments->arguments.size == 0) { return NULL; }
|
|
373
|
+
|
|
374
|
+
pm_node_t* last_argument = arguments->arguments.nodes[arguments->arguments.size - 1];
|
|
375
|
+
|
|
376
|
+
if (last_argument->type != PM_KEYWORD_HASH_NODE) { return NULL; }
|
|
377
|
+
|
|
378
|
+
pm_keyword_hash_node_t* hash = (pm_keyword_hash_node_t*) last_argument;
|
|
379
|
+
hb_buffer_T buffer;
|
|
380
|
+
hb_buffer_init(&buffer, 64, allocator);
|
|
381
|
+
bool first = true;
|
|
382
|
+
|
|
383
|
+
for (size_t i = 0; i < hash->elements.size; i++) {
|
|
384
|
+
pm_node_t* element = hash->elements.nodes[i];
|
|
385
|
+
|
|
386
|
+
if (element->type != PM_ASSOC_NODE) { continue; }
|
|
387
|
+
|
|
388
|
+
pm_assoc_node_t* assoc = (pm_assoc_node_t*) element;
|
|
389
|
+
|
|
390
|
+
if (assoc->key->type != PM_SYMBOL_NODE) { continue; }
|
|
391
|
+
|
|
392
|
+
pm_symbol_node_t* key_node = (pm_symbol_node_t*) assoc->key;
|
|
393
|
+
size_t key_length = pm_string_length(&key_node->unescaped);
|
|
394
|
+
const char* key_source = (const char*) pm_string_source(&key_node->unescaped);
|
|
395
|
+
|
|
396
|
+
bool is_path_option = false;
|
|
397
|
+
|
|
398
|
+
for (const char** option = option_names; *option != NULL; option++) {
|
|
399
|
+
if (key_length == strlen(*option) && strncmp(key_source, *option, key_length) == 0) {
|
|
400
|
+
is_path_option = true;
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (!is_path_option) { continue; }
|
|
406
|
+
|
|
407
|
+
if (!first) { hb_buffer_append(&buffer, ", "); }
|
|
408
|
+
first = false;
|
|
409
|
+
|
|
410
|
+
size_t key_source_length = assoc->key->location.end - assoc->key->location.start;
|
|
411
|
+
hb_buffer_append_with_length(&buffer, (const char*) assoc->key->location.start, key_source_length);
|
|
412
|
+
hb_buffer_append(&buffer, " ");
|
|
413
|
+
|
|
414
|
+
size_t value_source_length = assoc->value->location.end - assoc->value->location.start;
|
|
415
|
+
hb_buffer_append_with_length(&buffer, (const char*) assoc->value->location.start, value_source_length);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (first) {
|
|
419
|
+
hb_buffer_free(&buffer);
|
|
420
|
+
return NULL;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
char* result = hb_allocator_strdup(allocator, hb_buffer_value(&buffer));
|
|
424
|
+
hb_buffer_free(&buffer);
|
|
425
|
+
|
|
426
|
+
return result;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
static AST_NODE_T* remove_attribute_by_name(hb_array_T* attributes, const char* name) {
|
|
430
|
+
if (!attributes) { return NULL; }
|
|
431
|
+
|
|
432
|
+
for (size_t index = 0; index < hb_array_size(attributes); index++) {
|
|
433
|
+
AST_NODE_T* attribute = hb_array_get(attributes, index);
|
|
434
|
+
|
|
435
|
+
if (attribute->type != AST_HTML_ATTRIBUTE_NODE) { continue; }
|
|
436
|
+
|
|
437
|
+
AST_HTML_ATTRIBUTE_NODE_T* html_attribute = (AST_HTML_ATTRIBUTE_NODE_T*) attribute;
|
|
438
|
+
|
|
439
|
+
if (!html_attribute->name || !html_attribute->name->children || !hb_array_size(html_attribute->name->children)) {
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
AST_LITERAL_NODE_T* literal = (AST_LITERAL_NODE_T*) hb_array_get(html_attribute->name->children, 0);
|
|
444
|
+
|
|
445
|
+
if (hb_string_equals(literal->content, hb_string((char*) name))) {
|
|
446
|
+
hb_array_remove(attributes, index);
|
|
447
|
+
return attribute;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
return NULL;
|
|
452
|
+
}
|
|
233
453
|
static AST_NODE_T* transform_tag_helper_with_attributes(
|
|
234
454
|
AST_ERB_CONTENT_NODE_T* erb_node,
|
|
235
455
|
analyze_ruby_context_T* context,
|
|
@@ -261,6 +481,116 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
|
|
|
261
481
|
);
|
|
262
482
|
}
|
|
263
483
|
|
|
484
|
+
if (attributes && handler->name
|
|
485
|
+
&& (strcmp(handler->name, "javascript_include_tag") == 0 || strcmp(handler->name, "javascript_tag") == 0)) {
|
|
486
|
+
resolve_nonce_attribute(attributes, allocator);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
char* path_options = NULL;
|
|
490
|
+
|
|
491
|
+
if (attributes && handler->name && strcmp(handler->name, "javascript_include_tag") == 0) {
|
|
492
|
+
path_options = extract_path_options_from_keyword_hash(
|
|
493
|
+
parse_context->info->call_node,
|
|
494
|
+
JAVASCRIPT_INCLUDE_TAG_PATH_OPTIONS,
|
|
495
|
+
allocator
|
|
496
|
+
);
|
|
497
|
+
|
|
498
|
+
remove_attribute_by_name(attributes, "extname");
|
|
499
|
+
remove_attribute_by_name(attributes, "host");
|
|
500
|
+
remove_attribute_by_name(attributes, "protocol");
|
|
501
|
+
remove_attribute_by_name(attributes, "skip-pipeline");
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (attributes && handler->name && strcmp(handler->name, "image_tag") == 0) {
|
|
505
|
+
path_options =
|
|
506
|
+
extract_path_options_from_keyword_hash(parse_context->info->call_node, IMAGE_TAG_PATH_OPTIONS, allocator);
|
|
507
|
+
remove_attribute_by_name(attributes, "skip-pipeline");
|
|
508
|
+
|
|
509
|
+
AST_NODE_T* size_node = remove_attribute_by_name(attributes, "size");
|
|
510
|
+
|
|
511
|
+
if (size_node && size_node->type == AST_HTML_ATTRIBUTE_NODE) {
|
|
512
|
+
AST_HTML_ATTRIBUTE_NODE_T* size_attribute_node = (AST_HTML_ATTRIBUTE_NODE_T*) size_node;
|
|
513
|
+
|
|
514
|
+
if (size_attribute_node->value && size_attribute_node->value->children
|
|
515
|
+
&& hb_array_size(size_attribute_node->value->children) > 0) {
|
|
516
|
+
AST_NODE_T* value_node = (AST_NODE_T*) hb_array_get(size_attribute_node->value->children, 0);
|
|
517
|
+
position_T position = size_attribute_node->base.location.start;
|
|
518
|
+
|
|
519
|
+
if (value_node->type == AST_LITERAL_NODE) {
|
|
520
|
+
AST_LITERAL_NODE_T* literal = (AST_LITERAL_NODE_T*) value_node;
|
|
521
|
+
char* size_string = hb_allocator_strndup(allocator, literal->content.data, literal->content.length);
|
|
522
|
+
|
|
523
|
+
if (size_string) {
|
|
524
|
+
const char* x_position = strchr(size_string, 'x');
|
|
525
|
+
char width_string[32];
|
|
526
|
+
char height_string[32];
|
|
527
|
+
|
|
528
|
+
if (x_position) {
|
|
529
|
+
size_t width_length = (size_t) (x_position - size_string);
|
|
530
|
+
strncpy(width_string, size_string, width_length);
|
|
531
|
+
width_string[width_length] = '\0';
|
|
532
|
+
strncpy(height_string, x_position + 1, sizeof(height_string) - 1);
|
|
533
|
+
height_string[sizeof(height_string) - 1] = '\0';
|
|
534
|
+
} else {
|
|
535
|
+
strncpy(width_string, size_string, sizeof(width_string) - 1);
|
|
536
|
+
width_string[sizeof(width_string) - 1] = '\0';
|
|
537
|
+
strncpy(height_string, size_string, sizeof(height_string) - 1);
|
|
538
|
+
height_string[sizeof(height_string) - 1] = '\0';
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
AST_HTML_ATTRIBUTE_NODE_T* width_attribute =
|
|
542
|
+
create_html_attribute_node("width", width_string, position, position, allocator);
|
|
543
|
+
AST_HTML_ATTRIBUTE_NODE_T* height_attribute =
|
|
544
|
+
create_html_attribute_node("height", height_string, position, position, allocator);
|
|
545
|
+
|
|
546
|
+
if (width_attribute) { hb_array_append(attributes, (AST_NODE_T*) width_attribute); }
|
|
547
|
+
if (height_attribute) { hb_array_append(attributes, (AST_NODE_T*) height_attribute); }
|
|
548
|
+
|
|
549
|
+
hb_allocator_dealloc(allocator, size_string);
|
|
550
|
+
}
|
|
551
|
+
} else if (value_node->type == AST_RUBY_LITERAL_NODE) {
|
|
552
|
+
AST_RUBY_LITERAL_NODE_T* ruby_literal = (AST_RUBY_LITERAL_NODE_T*) value_node;
|
|
553
|
+
char* size_expression =
|
|
554
|
+
hb_allocator_strndup(allocator, ruby_literal->content.data, ruby_literal->content.length);
|
|
555
|
+
|
|
556
|
+
if (size_expression) {
|
|
557
|
+
hb_buffer_T width_buffer;
|
|
558
|
+
hb_buffer_init(&width_buffer, ruby_literal->content.length + 32, allocator);
|
|
559
|
+
hb_buffer_append(&width_buffer, size_expression);
|
|
560
|
+
hb_buffer_append(&width_buffer, ".to_s.split(\"x\", 2)[0]");
|
|
561
|
+
|
|
562
|
+
hb_buffer_T height_buffer;
|
|
563
|
+
hb_buffer_init(&height_buffer, ruby_literal->content.length + 32, allocator);
|
|
564
|
+
hb_buffer_append(&height_buffer, size_expression);
|
|
565
|
+
hb_buffer_append(&height_buffer, ".to_s.split(\"x\", 2)[-1]");
|
|
566
|
+
|
|
567
|
+
AST_HTML_ATTRIBUTE_NODE_T* width_attribute = create_html_attribute_with_ruby_literal(
|
|
568
|
+
"width",
|
|
569
|
+
hb_buffer_value(&width_buffer),
|
|
570
|
+
position,
|
|
571
|
+
position,
|
|
572
|
+
allocator
|
|
573
|
+
);
|
|
574
|
+
AST_HTML_ATTRIBUTE_NODE_T* height_attribute = create_html_attribute_with_ruby_literal(
|
|
575
|
+
"height",
|
|
576
|
+
hb_buffer_value(&height_buffer),
|
|
577
|
+
position,
|
|
578
|
+
position,
|
|
579
|
+
allocator
|
|
580
|
+
);
|
|
581
|
+
|
|
582
|
+
if (width_attribute) { hb_array_append(attributes, (AST_NODE_T*) width_attribute); }
|
|
583
|
+
if (height_attribute) { hb_array_append(attributes, (AST_NODE_T*) height_attribute); }
|
|
584
|
+
|
|
585
|
+
hb_buffer_free(&width_buffer);
|
|
586
|
+
hb_buffer_free(&height_buffer);
|
|
587
|
+
hb_allocator_dealloc(allocator, size_expression);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
264
594
|
char* helper_content = NULL;
|
|
265
595
|
bool content_is_ruby_expression = false;
|
|
266
596
|
|
|
@@ -340,7 +670,7 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
|
|
|
340
670
|
quoted_source[quoted_length - 1] = '"';
|
|
341
671
|
quoted_source[quoted_length] = '\0';
|
|
342
672
|
|
|
343
|
-
source_attribute_value = wrap_in_javascript_path(quoted_source, quoted_length, allocator);
|
|
673
|
+
source_attribute_value = wrap_in_javascript_path(quoted_source, quoted_length, path_options, allocator);
|
|
344
674
|
hb_allocator_dealloc(allocator, quoted_source);
|
|
345
675
|
}
|
|
346
676
|
|
|
@@ -356,6 +686,50 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
|
|
|
356
686
|
}
|
|
357
687
|
}
|
|
358
688
|
|
|
689
|
+
if (detect_image_tag(parse_context->info->call_node, &parse_context->parser)
|
|
690
|
+
&& parse_context->info->call_node->arguments && parse_context->info->call_node->arguments->arguments.size >= 1) {
|
|
691
|
+
char* source_value = extract_image_tag_src(parse_context->info->call_node, &parse_context->parser, allocator);
|
|
692
|
+
|
|
693
|
+
if (source_value) {
|
|
694
|
+
if (!attributes) { attributes = hb_array_init(4, allocator); }
|
|
695
|
+
|
|
696
|
+
pm_node_t* first_argument = parse_context->info->call_node->arguments->arguments.nodes[0];
|
|
697
|
+
position_T source_start, source_end;
|
|
698
|
+
prism_node_location_to_positions(&first_argument->location, parse_context, &source_start, &source_end);
|
|
699
|
+
bool source_is_string = (first_argument->type == PM_STRING_NODE);
|
|
700
|
+
bool source_is_path_helper = is_route_helper_node(first_argument, &parse_context->parser);
|
|
701
|
+
|
|
702
|
+
size_t source_length = strlen(source_value);
|
|
703
|
+
bool is_url = image_tag_source_is_url(source_value, source_length);
|
|
704
|
+
|
|
705
|
+
char* source_attribute_value = source_value;
|
|
706
|
+
|
|
707
|
+
if (source_is_string && !is_url) {
|
|
708
|
+
size_t quoted_length = source_length + 2;
|
|
709
|
+
char* quoted_source = hb_allocator_alloc(allocator, quoted_length + 1);
|
|
710
|
+
quoted_source[0] = '"';
|
|
711
|
+
memcpy(quoted_source + 1, source_value, source_length);
|
|
712
|
+
quoted_source[quoted_length - 1] = '"';
|
|
713
|
+
quoted_source[quoted_length] = '\0';
|
|
714
|
+
|
|
715
|
+
source_attribute_value = wrap_in_image_path(quoted_source, quoted_length, path_options, allocator);
|
|
716
|
+
hb_allocator_dealloc(allocator, quoted_source);
|
|
717
|
+
} else if (!source_is_string && !is_url && !source_is_path_helper) {
|
|
718
|
+
source_attribute_value = wrap_in_image_path(source_value, source_length, path_options, allocator);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
AST_HTML_ATTRIBUTE_NODE_T* source_attribute =
|
|
722
|
+
is_url
|
|
723
|
+
? create_html_attribute_node("src", source_attribute_value, source_start, source_end, allocator)
|
|
724
|
+
: create_html_attribute_with_ruby_literal("src", source_attribute_value, source_start, source_end, allocator);
|
|
725
|
+
|
|
726
|
+
if (source_attribute) { attributes = prepend_attribute(attributes, (AST_NODE_T*) source_attribute, allocator); }
|
|
727
|
+
if (source_attribute_value != source_value) { hb_allocator_dealloc(allocator, source_attribute_value); }
|
|
728
|
+
|
|
729
|
+
hb_allocator_dealloc(allocator, source_value);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
359
733
|
token_T* tag_name_token =
|
|
360
734
|
tag_name ? create_synthetic_token(allocator, tag_name, TOKEN_IDENTIFIER, tag_name_start, tag_name_end) : NULL;
|
|
361
735
|
|
|
@@ -374,9 +748,56 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
|
|
|
374
748
|
);
|
|
375
749
|
|
|
376
750
|
hb_array_T* body = hb_array_init(1, allocator);
|
|
377
|
-
|
|
751
|
+
hb_array_T* element_errors = hb_array_init(0, allocator);
|
|
752
|
+
bool is_void = tag_name && is_void_element(hb_string_from_c_string(tag_name))
|
|
753
|
+
&& (string_equals(handler->name, "tag") || string_equals(handler->name, "content_tag")
|
|
754
|
+
|| string_equals(handler->name, "image_tag"));
|
|
378
755
|
|
|
379
756
|
if (helper_content) {
|
|
757
|
+
if (is_void && tag_name) {
|
|
758
|
+
hb_buffer_T helper_name_buffer;
|
|
759
|
+
hb_buffer_init(&helper_name_buffer, 64, allocator);
|
|
760
|
+
|
|
761
|
+
if (string_equals(handler->name, "tag")) {
|
|
762
|
+
hb_buffer_append(&helper_name_buffer, "tag.");
|
|
763
|
+
hb_buffer_append(&helper_name_buffer, tag_name);
|
|
764
|
+
} else {
|
|
765
|
+
hb_buffer_append(&helper_name_buffer, handler->name);
|
|
766
|
+
hb_buffer_append(&helper_name_buffer, " :");
|
|
767
|
+
hb_buffer_append(&helper_name_buffer, tag_name);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
hb_string_T helper_name = hb_string_from_c_string(hb_buffer_value(&helper_name_buffer));
|
|
771
|
+
|
|
772
|
+
position_T content_start = erb_node->base.location.start;
|
|
773
|
+
position_T content_end = erb_node->base.location.end;
|
|
774
|
+
|
|
775
|
+
pm_call_node_t* call = parse_context->info->call_node;
|
|
776
|
+
|
|
777
|
+
if (call && call->arguments) {
|
|
778
|
+
size_t content_arg_index = string_equals(handler->name, "content_tag") ? 1 : 0;
|
|
779
|
+
|
|
780
|
+
if (call->arguments->arguments.size > content_arg_index) {
|
|
781
|
+
pm_node_t* content_node = call->arguments->arguments.nodes[content_arg_index];
|
|
782
|
+
prism_node_location_to_positions(&content_node->location, parse_context, &content_start, &content_end);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
pm_call_node_t* void_call = parse_context->info->call_node;
|
|
787
|
+
bool content_from_block = void_call && void_call->block && void_call->block->type == PM_BLOCK_NODE;
|
|
788
|
+
hb_string_T content_type = content_from_block ? hb_string("a block") : hb_string("a positional argument");
|
|
789
|
+
|
|
790
|
+
append_void_element_content_error(
|
|
791
|
+
tag_name_token,
|
|
792
|
+
helper_name,
|
|
793
|
+
content_type,
|
|
794
|
+
content_start,
|
|
795
|
+
content_end,
|
|
796
|
+
allocator,
|
|
797
|
+
element_errors
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
|
|
380
801
|
append_body_content_node(
|
|
381
802
|
body,
|
|
382
803
|
helper_content,
|
|
@@ -410,7 +831,7 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
|
|
|
410
831
|
handler->source,
|
|
411
832
|
erb_node->base.location.start,
|
|
412
833
|
erb_node->base.location.end,
|
|
413
|
-
|
|
834
|
+
element_errors,
|
|
414
835
|
allocator
|
|
415
836
|
);
|
|
416
837
|
|
|
@@ -438,6 +859,7 @@ static AST_NODE_T* create_javascript_include_tag_element(
|
|
|
438
859
|
tag_helper_parse_context_T* parse_context,
|
|
439
860
|
pm_node_t* source_argument,
|
|
440
861
|
hb_array_T* shared_attributes,
|
|
862
|
+
const char* path_options,
|
|
441
863
|
hb_allocator_T* allocator
|
|
442
864
|
) {
|
|
443
865
|
position_T tag_name_start, tag_name_end;
|
|
@@ -478,7 +900,7 @@ static AST_NODE_T* create_javascript_include_tag_element(
|
|
|
478
900
|
quoted_source[quoted_length - 1] = '"';
|
|
479
901
|
quoted_source[quoted_length] = '\0';
|
|
480
902
|
|
|
481
|
-
source_attribute_value = wrap_in_javascript_path(quoted_source, quoted_length, allocator);
|
|
903
|
+
source_attribute_value = wrap_in_javascript_path(quoted_source, quoted_length, path_options, allocator);
|
|
482
904
|
hb_allocator_dealloc(allocator, quoted_source);
|
|
483
905
|
}
|
|
484
906
|
|
|
@@ -551,12 +973,27 @@ static hb_array_T* transform_javascript_include_tag_multi_source(
|
|
|
551
973
|
);
|
|
552
974
|
if (!shared_attributes) { shared_attributes = hb_array_init(0, allocator); }
|
|
553
975
|
|
|
976
|
+
resolve_nonce_attribute(shared_attributes, allocator);
|
|
977
|
+
|
|
978
|
+
char* path_options =
|
|
979
|
+
extract_path_options_from_keyword_hash(call_node, JAVASCRIPT_INCLUDE_TAG_PATH_OPTIONS, allocator);
|
|
980
|
+
remove_attribute_by_name(shared_attributes, "extname");
|
|
981
|
+
remove_attribute_by_name(shared_attributes, "host");
|
|
982
|
+
remove_attribute_by_name(shared_attributes, "protocol");
|
|
983
|
+
remove_attribute_by_name(shared_attributes, "skip-pipeline");
|
|
984
|
+
|
|
554
985
|
hb_array_T* elements = hb_array_init(source_count * 2, allocator);
|
|
555
986
|
|
|
556
987
|
for (size_t i = 0; i < source_count; i++) {
|
|
557
988
|
pm_node_t* source_arg = call_node->arguments->arguments.nodes[i];
|
|
558
|
-
AST_NODE_T* element =
|
|
559
|
-
|
|
989
|
+
AST_NODE_T* element = create_javascript_include_tag_element(
|
|
990
|
+
erb_node,
|
|
991
|
+
parse_context,
|
|
992
|
+
source_arg,
|
|
993
|
+
shared_attributes,
|
|
994
|
+
path_options,
|
|
995
|
+
allocator
|
|
996
|
+
);
|
|
560
997
|
|
|
561
998
|
if (element) {
|
|
562
999
|
if (hb_array_size(elements) > 0) {
|
|
@@ -578,6 +1015,42 @@ static hb_array_T* transform_javascript_include_tag_multi_source(
|
|
|
578
1015
|
return elements;
|
|
579
1016
|
}
|
|
580
1017
|
|
|
1018
|
+
static bool erb_content_is_end_keyword(hb_string_T content) {
|
|
1019
|
+
const char* start = content.data;
|
|
1020
|
+
const char* end = content.data + content.length;
|
|
1021
|
+
|
|
1022
|
+
while (start < end && is_whitespace(*start)) {
|
|
1023
|
+
start++;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
while (end > start && is_whitespace(*(end - 1))) {
|
|
1027
|
+
end--;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
return (size_t) (end - start) == 3 && start[0] == 'e' && start[1] == 'n' && start[2] == 'd';
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
static AST_ERB_CONTENT_NODE_T* find_swallowed_erb_end_node(hb_array_T* nodes) {
|
|
1034
|
+
if (!nodes) { return NULL; }
|
|
1035
|
+
|
|
1036
|
+
for (size_t i = 0; i < hb_array_size(nodes); i++) {
|
|
1037
|
+
AST_NODE_T* node = (AST_NODE_T*) hb_array_get(nodes, i);
|
|
1038
|
+
if (!node) { continue; }
|
|
1039
|
+
|
|
1040
|
+
if (node->type == AST_ERB_CONTENT_NODE) {
|
|
1041
|
+
AST_ERB_CONTENT_NODE_T* erb = (AST_ERB_CONTENT_NODE_T*) node;
|
|
1042
|
+
if (erb->content && erb_content_is_end_keyword(erb->content->value)) { return erb; }
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
if (node->type == AST_HTML_OPEN_TAG_NODE) {
|
|
1046
|
+
AST_ERB_CONTENT_NODE_T* found = find_swallowed_erb_end_node(((AST_HTML_OPEN_TAG_NODE_T*) node)->children);
|
|
1047
|
+
if (found) { return found; }
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
return NULL;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
581
1054
|
static AST_NODE_T* transform_erb_block_to_tag_helper(
|
|
582
1055
|
AST_ERB_BLOCK_NODE_T* block_node,
|
|
583
1056
|
analyze_ruby_context_T* context,
|
|
@@ -598,6 +1071,7 @@ static AST_NODE_T* transform_erb_block_to_tag_helper(
|
|
|
598
1071
|
);
|
|
599
1072
|
|
|
600
1073
|
hb_array_T* attributes = NULL;
|
|
1074
|
+
|
|
601
1075
|
if (parse_context->info->call_node) {
|
|
602
1076
|
attributes = extract_html_attributes_from_call_node(
|
|
603
1077
|
parse_context->info->call_node,
|
|
@@ -608,6 +1082,12 @@ static AST_NODE_T* transform_erb_block_to_tag_helper(
|
|
|
608
1082
|
);
|
|
609
1083
|
}
|
|
610
1084
|
|
|
1085
|
+
if (attributes && parse_context->matched_handler && parse_context->matched_handler->name
|
|
1086
|
+
&& (strcmp(parse_context->matched_handler->name, "javascript_include_tag") == 0
|
|
1087
|
+
|| strcmp(parse_context->matched_handler->name, "javascript_tag") == 0)) {
|
|
1088
|
+
resolve_nonce_attribute(attributes, allocator);
|
|
1089
|
+
}
|
|
1090
|
+
|
|
611
1091
|
if (detect_link_to(parse_context->info->call_node, &parse_context->parser)
|
|
612
1092
|
&& parse_context->info->call_node->arguments && parse_context->info->call_node->arguments->arguments.size >= 1) {
|
|
613
1093
|
pm_node_t* first_argument = parse_context->info->call_node->arguments->arguments.nodes[0];
|
|
@@ -682,26 +1162,85 @@ static AST_NODE_T* transform_erb_block_to_tag_helper(
|
|
|
682
1162
|
);
|
|
683
1163
|
|
|
684
1164
|
hb_array_T* body = block_node->body ? block_node->body : hb_array_init(0, allocator);
|
|
1165
|
+
hb_array_T* element_errors = hb_array_init(0, allocator);
|
|
685
1166
|
AST_NODE_T* close_tag = (AST_NODE_T*) block_node->end_node;
|
|
1167
|
+
position_T element_end = block_node->base.location.end;
|
|
1168
|
+
|
|
1169
|
+
bool is_void = tag_name && is_void_element(hb_string_from_c_string(tag_name)) && parse_context->matched_handler
|
|
1170
|
+
&& parse_context->matched_handler->name
|
|
1171
|
+
&& (string_equals(parse_context->matched_handler->name, "tag")
|
|
1172
|
+
|| string_equals(parse_context->matched_handler->name, "content_tag")
|
|
1173
|
+
|| string_equals(parse_context->matched_handler->name, "image_tag"));
|
|
1174
|
+
|
|
1175
|
+
if (is_void) {
|
|
1176
|
+
hb_buffer_T helper_name_buffer;
|
|
1177
|
+
hb_buffer_init(&helper_name_buffer, 64, allocator);
|
|
1178
|
+
|
|
1179
|
+
if (string_equals(parse_context->matched_handler->name, "tag")) {
|
|
1180
|
+
hb_buffer_append(&helper_name_buffer, "tag.");
|
|
1181
|
+
hb_buffer_append(&helper_name_buffer, tag_name);
|
|
1182
|
+
} else {
|
|
1183
|
+
hb_buffer_append(&helper_name_buffer, parse_context->matched_handler->name);
|
|
1184
|
+
hb_buffer_append(&helper_name_buffer, " :");
|
|
1185
|
+
hb_buffer_append(&helper_name_buffer, tag_name);
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
hb_string_T helper_name = hb_string_from_c_string(hb_buffer_value(&helper_name_buffer));
|
|
1189
|
+
|
|
1190
|
+
append_void_element_content_error(
|
|
1191
|
+
tag_name_token,
|
|
1192
|
+
helper_name,
|
|
1193
|
+
hb_string("a block"),
|
|
1194
|
+
block_node->base.location.start,
|
|
1195
|
+
block_node->base.location.end,
|
|
1196
|
+
allocator,
|
|
1197
|
+
element_errors
|
|
1198
|
+
);
|
|
1199
|
+
}
|
|
686
1200
|
|
|
687
1201
|
if (tag_name && parser_is_foreign_content_tag(hb_string_from_c_string(tag_name)) && context->source
|
|
688
1202
|
&& block_node->body && hb_array_size(block_node->body) > 0) {
|
|
689
1203
|
size_t start_offset = block_node->tag_closing->range.to;
|
|
690
|
-
size_t end_offset =
|
|
1204
|
+
size_t end_offset = 0;
|
|
1205
|
+
|
|
1206
|
+
if (block_node->end_node && block_node->end_node->tag_opening) {
|
|
1207
|
+
end_offset = block_node->end_node->tag_opening->range.from;
|
|
1208
|
+
} else {
|
|
1209
|
+
AST_ERB_CONTENT_NODE_T* swallowed_end = find_swallowed_erb_end_node(block_node->body);
|
|
1210
|
+
|
|
1211
|
+
if (swallowed_end && swallowed_end->tag_opening) {
|
|
1212
|
+
end_offset = swallowed_end->tag_opening->range.from;
|
|
1213
|
+
|
|
1214
|
+
AST_ERB_END_NODE_T* end_node = ast_erb_end_node_init(
|
|
1215
|
+
swallowed_end->tag_opening,
|
|
1216
|
+
swallowed_end->content,
|
|
1217
|
+
swallowed_end->tag_closing,
|
|
1218
|
+
swallowed_end->base.location.start,
|
|
1219
|
+
swallowed_end->base.location.end,
|
|
1220
|
+
hb_array_init(0, allocator),
|
|
1221
|
+
allocator
|
|
1222
|
+
);
|
|
1223
|
+
|
|
1224
|
+
close_tag = (AST_NODE_T*) end_node;
|
|
1225
|
+
element_end = close_tag->location.end;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
691
1228
|
|
|
692
1229
|
if (end_offset > start_offset) {
|
|
693
1230
|
position_T body_start = block_node->tag_closing->location.end;
|
|
694
|
-
position_T body_end = block_node->end_node->tag_opening->location.start;
|
|
695
1231
|
|
|
696
1232
|
size_t content_length = end_offset - start_offset;
|
|
697
1233
|
char* raw_copy = hb_allocator_strndup(allocator, context->source + start_offset, content_length);
|
|
698
|
-
hb_string_T raw_content = { .data = raw_copy, .length = content_length };
|
|
699
1234
|
|
|
700
|
-
|
|
701
|
-
|
|
1235
|
+
parser_options_T body_options = HERB_DEFAULT_PARSER_OPTIONS;
|
|
1236
|
+
body_options.html = false;
|
|
1237
|
+
body_options.analyze = false;
|
|
1238
|
+
body_options.strict = false;
|
|
1239
|
+
body_options.start_line = body_start.line;
|
|
1240
|
+
body_options.start_column = body_start.column;
|
|
702
1241
|
|
|
703
|
-
|
|
704
|
-
|
|
1242
|
+
AST_DOCUMENT_NODE_T* body_document = herb_parse(raw_copy, &body_options, allocator);
|
|
1243
|
+
body = body_document->children;
|
|
705
1244
|
}
|
|
706
1245
|
}
|
|
707
1246
|
|
|
@@ -709,12 +1248,12 @@ static AST_NODE_T* transform_erb_block_to_tag_helper(
|
|
|
709
1248
|
(AST_NODE_T*) open_tag_node,
|
|
710
1249
|
tag_name_token,
|
|
711
1250
|
body,
|
|
712
|
-
close_tag,
|
|
713
|
-
|
|
1251
|
+
is_void ? NULL : close_tag,
|
|
1252
|
+
is_void,
|
|
714
1253
|
parse_context->matched_handler->source,
|
|
715
1254
|
block_node->base.location.start,
|
|
716
|
-
|
|
717
|
-
|
|
1255
|
+
element_end,
|
|
1256
|
+
element_errors,
|
|
718
1257
|
allocator
|
|
719
1258
|
);
|
|
720
1259
|
|
|
@@ -763,6 +1302,12 @@ static AST_NODE_T* transform_link_to_helper(
|
|
|
763
1302
|
char* content = hb_allocator_strndup(allocator, (const char*) second_arg->location.start, source_length);
|
|
764
1303
|
|
|
765
1304
|
if (content) {
|
|
1305
|
+
hb_buffer_T wrapped;
|
|
1306
|
+
hb_buffer_init(&wrapped, source_length + 32, allocator);
|
|
1307
|
+
hb_buffer_append(&wrapped, "tag.attributes(**");
|
|
1308
|
+
hb_buffer_append(&wrapped, content);
|
|
1309
|
+
hb_buffer_append(&wrapped, ")");
|
|
1310
|
+
|
|
766
1311
|
position_T position = prism_location_to_position_with_offset(
|
|
767
1312
|
&second_arg->location,
|
|
768
1313
|
parse_context->original_source,
|
|
@@ -771,7 +1316,7 @@ static AST_NODE_T* transform_link_to_helper(
|
|
|
771
1316
|
);
|
|
772
1317
|
|
|
773
1318
|
AST_RUBY_HTML_ATTRIBUTES_SPLAT_NODE_T* splat_node = ast_ruby_html_attributes_splat_node_init(
|
|
774
|
-
hb_string_from_c_string(
|
|
1319
|
+
hb_string_from_c_string(hb_buffer_value(&wrapped)),
|
|
775
1320
|
HB_STRING_EMPTY,
|
|
776
1321
|
position,
|
|
777
1322
|
position,
|
|
@@ -781,6 +1326,7 @@ static AST_NODE_T* transform_link_to_helper(
|
|
|
781
1326
|
|
|
782
1327
|
if (splat_node) { hb_array_append(attributes, (AST_NODE_T*) splat_node); }
|
|
783
1328
|
|
|
1329
|
+
hb_buffer_free(&wrapped);
|
|
784
1330
|
hb_allocator_dealloc(allocator, content);
|
|
785
1331
|
}
|
|
786
1332
|
}
|
|
@@ -946,21 +1492,8 @@ static AST_NODE_T* transform_link_to_helper(
|
|
|
946
1492
|
return (AST_NODE_T*) element;
|
|
947
1493
|
}
|
|
948
1494
|
|
|
949
|
-
void
|
|
950
|
-
if (!
|
|
951
|
-
|
|
952
|
-
hb_array_T* array = NULL;
|
|
953
|
-
|
|
954
|
-
switch (node->type) {
|
|
955
|
-
case AST_DOCUMENT_NODE: array = ((AST_DOCUMENT_NODE_T*) node)->children; break;
|
|
956
|
-
case AST_HTML_ELEMENT_NODE: array = ((AST_HTML_ELEMENT_NODE_T*) node)->body; break;
|
|
957
|
-
case AST_HTML_OPEN_TAG_NODE: array = ((AST_HTML_OPEN_TAG_NODE_T*) node)->children; break;
|
|
958
|
-
case AST_HTML_ATTRIBUTE_VALUE_NODE: array = ((AST_HTML_ATTRIBUTE_VALUE_NODE_T*) node)->children; break;
|
|
959
|
-
case AST_ERB_BLOCK_NODE: array = ((AST_ERB_BLOCK_NODE_T*) node)->body; break;
|
|
960
|
-
default: return;
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
if (!array) { return; }
|
|
1495
|
+
void transform_tag_helper_array(hb_array_T* array, analyze_ruby_context_T* context) {
|
|
1496
|
+
if (!array || !context) { return; }
|
|
964
1497
|
|
|
965
1498
|
for (size_t i = 0; i < hb_array_size(array); i++) {
|
|
966
1499
|
AST_NODE_T* child = hb_array_get(array, i);
|
|
@@ -985,6 +1518,7 @@ void transform_tag_helper_blocks(const AST_NODE_T* node, analyze_ruby_context_T*
|
|
|
985
1518
|
|
|
986
1519
|
if (parse_context) {
|
|
987
1520
|
replacement = transform_erb_block_to_tag_helper(block_node, context, parse_context);
|
|
1521
|
+
replacement = wrap_in_conditional_if_needed(replacement, parse_context, context->allocator);
|
|
988
1522
|
free_tag_helper_parse_context(parse_context);
|
|
989
1523
|
}
|
|
990
1524
|
|
|
@@ -1042,18 +1576,232 @@ void transform_tag_helper_blocks(const AST_NODE_T* node, analyze_ruby_context_T*
|
|
|
1042
1576
|
}
|
|
1043
1577
|
} else if (strcmp(parse_context->matched_handler->name, "link_to") == 0) {
|
|
1044
1578
|
replacement = transform_link_to_helper(erb_node, context, parse_context);
|
|
1579
|
+
} else if (string_equals(parse_context->matched_handler->name, "tag") && parse_context->info->tag_name
|
|
1580
|
+
&& string_equals(parse_context->info->tag_name, "attributes")) {
|
|
1581
|
+
hb_array_T* attributes = NULL;
|
|
1582
|
+
|
|
1583
|
+
if (parse_context->info->call_node) {
|
|
1584
|
+
attributes = extract_html_attributes_from_call_node(
|
|
1585
|
+
parse_context->info->call_node,
|
|
1586
|
+
parse_context->prism_source,
|
|
1587
|
+
parse_context->original_source,
|
|
1588
|
+
parse_context->erb_content_offset,
|
|
1589
|
+
context->allocator
|
|
1590
|
+
);
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
if (attributes && hb_array_size(attributes) > 0) {
|
|
1594
|
+
size_t old_size = hb_array_size(array);
|
|
1595
|
+
size_t attributes_size = hb_array_size(attributes);
|
|
1596
|
+
hb_array_T* new_array = hb_array_init(old_size - 1 + attributes_size, context->allocator);
|
|
1597
|
+
|
|
1598
|
+
for (size_t j = 0; j < old_size; j++) {
|
|
1599
|
+
if (j == i) {
|
|
1600
|
+
for (size_t k = 0; k < attributes_size; k++) {
|
|
1601
|
+
hb_array_append(new_array, hb_array_get(attributes, k));
|
|
1602
|
+
}
|
|
1603
|
+
} else {
|
|
1604
|
+
hb_array_append(new_array, hb_array_get(array, j));
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
array->items = new_array->items;
|
|
1609
|
+
array->size = new_array->size;
|
|
1610
|
+
array->capacity = new_array->capacity;
|
|
1611
|
+
|
|
1612
|
+
i += attributes_size - 1;
|
|
1613
|
+
}
|
|
1045
1614
|
} else {
|
|
1046
1615
|
replacement = transform_tag_helper_with_attributes(erb_node, context, parse_context);
|
|
1047
1616
|
}
|
|
1048
1617
|
|
|
1618
|
+
replacement = wrap_in_conditional_if_needed(replacement, parse_context, context->allocator);
|
|
1049
1619
|
free_tag_helper_parse_context(parse_context);
|
|
1050
1620
|
}
|
|
1051
1621
|
|
|
1052
1622
|
free(erb_string);
|
|
1053
1623
|
}
|
|
1624
|
+
} else if (child->type == AST_HTML_ATTRIBUTE_NODE) {
|
|
1625
|
+
AST_HTML_ATTRIBUTE_NODE_T* attribute_node = (AST_HTML_ATTRIBUTE_NODE_T*) child;
|
|
1626
|
+
|
|
1627
|
+
if (attribute_node->name && !attribute_node->equals && !attribute_node->value && attribute_node->name->children
|
|
1628
|
+
&& hb_array_size(attribute_node->name->children) == 1) {
|
|
1629
|
+
AST_NODE_T* name_child = hb_array_get(attribute_node->name->children, 0);
|
|
1630
|
+
|
|
1631
|
+
if (name_child && name_child->type == AST_ERB_CONTENT_NODE) {
|
|
1632
|
+
AST_ERB_CONTENT_NODE_T* erb_node = (AST_ERB_CONTENT_NODE_T*) name_child;
|
|
1633
|
+
token_T* erb_content = erb_node->content;
|
|
1634
|
+
|
|
1635
|
+
if (erb_content && !hb_string_is_empty(erb_content->value)) {
|
|
1636
|
+
char* erb_string = hb_string_to_c_string_using_malloc(erb_content->value);
|
|
1637
|
+
size_t erb_content_offset = 0;
|
|
1638
|
+
|
|
1639
|
+
if (context->source) {
|
|
1640
|
+
erb_content_offset = calculate_byte_offset_from_position(context->source, erb_content->location.start);
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
tag_helper_parse_context_T* parse_context =
|
|
1644
|
+
parse_tag_helper_content(erb_string, context->source, erb_content_offset, context->allocator);
|
|
1645
|
+
|
|
1646
|
+
if (parse_context && string_equals(parse_context->matched_handler->name, "tag")
|
|
1647
|
+
&& parse_context->info->tag_name && string_equals(parse_context->info->tag_name, "attributes")) {
|
|
1648
|
+
hb_array_T* attributes = NULL;
|
|
1649
|
+
|
|
1650
|
+
if (parse_context->info->call_node) {
|
|
1651
|
+
attributes = extract_html_attributes_from_call_node(
|
|
1652
|
+
parse_context->info->call_node,
|
|
1653
|
+
parse_context->prism_source,
|
|
1654
|
+
parse_context->original_source,
|
|
1655
|
+
parse_context->erb_content_offset,
|
|
1656
|
+
context->allocator
|
|
1657
|
+
);
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
if (attributes && hb_array_size(attributes) > 0) {
|
|
1661
|
+
size_t old_size = hb_array_size(array);
|
|
1662
|
+
size_t attributes_size = hb_array_size(attributes);
|
|
1663
|
+
hb_array_T* new_array = hb_array_init(old_size - 1 + attributes_size, context->allocator);
|
|
1664
|
+
|
|
1665
|
+
for (size_t j = 0; j < old_size; j++) {
|
|
1666
|
+
if (j == i) {
|
|
1667
|
+
for (size_t k = 0; k < attributes_size; k++) {
|
|
1668
|
+
hb_array_append(new_array, hb_array_get(attributes, k));
|
|
1669
|
+
}
|
|
1670
|
+
} else {
|
|
1671
|
+
hb_array_append(new_array, hb_array_get(array, j));
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
array->items = new_array->items;
|
|
1676
|
+
array->size = new_array->size;
|
|
1677
|
+
array->capacity = new_array->capacity;
|
|
1678
|
+
|
|
1679
|
+
i += attributes_size - 1;
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
free_tag_helper_parse_context(parse_context);
|
|
1683
|
+
} else if (parse_context) {
|
|
1684
|
+
free_tag_helper_parse_context(parse_context);
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
free(erb_string);
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
if (replacement) {
|
|
1694
|
+
position_T replacement_end = replacement->location.end;
|
|
1695
|
+
position_T original_end = child->location.end;
|
|
1696
|
+
bool has_trailing = replacement_end.line != original_end.line || replacement_end.column != original_end.column;
|
|
1697
|
+
|
|
1698
|
+
if (has_trailing && context->source && child->type == AST_ERB_BLOCK_NODE) {
|
|
1699
|
+
AST_HTML_ELEMENT_NODE_T* element = (AST_HTML_ELEMENT_NODE_T*) replacement;
|
|
1700
|
+
|
|
1701
|
+
if (replacement->type == AST_ERB_IF_NODE) {
|
|
1702
|
+
AST_ERB_IF_NODE_T* if_node = (AST_ERB_IF_NODE_T*) replacement;
|
|
1703
|
+
|
|
1704
|
+
if (if_node->statements && hb_array_size(if_node->statements) > 0) {
|
|
1705
|
+
element = (AST_HTML_ELEMENT_NODE_T*) hb_array_get(if_node->statements, 0);
|
|
1706
|
+
}
|
|
1707
|
+
} else if (replacement->type == AST_ERB_UNLESS_NODE) {
|
|
1708
|
+
AST_ERB_UNLESS_NODE_T* unless_node = (AST_ERB_UNLESS_NODE_T*) replacement;
|
|
1709
|
+
|
|
1710
|
+
if (unless_node->statements && hb_array_size(unless_node->statements) > 0) {
|
|
1711
|
+
element = (AST_HTML_ELEMENT_NODE_T*) hb_array_get(unless_node->statements, 0);
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
if (element->close_tag && element->close_tag->type == AST_ERB_END_NODE) {
|
|
1716
|
+
AST_ERB_END_NODE_T* close_erb = (AST_ERB_END_NODE_T*) element->close_tag;
|
|
1717
|
+
size_t trailing_start = close_erb->tag_closing->range.to;
|
|
1718
|
+
size_t source_length = strlen(context->source);
|
|
1719
|
+
size_t trailing_end = trailing_start;
|
|
1720
|
+
|
|
1721
|
+
while (trailing_end < source_length) {
|
|
1722
|
+
position_T position = position_from_source_with_offset(context->source, trailing_end);
|
|
1723
|
+
|
|
1724
|
+
if (position.line > original_end.line
|
|
1725
|
+
|| (position.line == original_end.line && position.column >= original_end.column)) {
|
|
1726
|
+
break;
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
trailing_end++;
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
if (trailing_end > trailing_start) {
|
|
1733
|
+
hb_string_T trailing_content =
|
|
1734
|
+
hb_string_from_data(context->source + trailing_start, trailing_end - trailing_start);
|
|
1735
|
+
AST_HTML_TEXT_NODE_T* trailing_text = ast_html_text_node_init(
|
|
1736
|
+
trailing_content,
|
|
1737
|
+
replacement_end,
|
|
1738
|
+
original_end,
|
|
1739
|
+
hb_array_init(0, context->allocator),
|
|
1740
|
+
context->allocator
|
|
1741
|
+
);
|
|
1742
|
+
|
|
1743
|
+
size_t old_size = hb_array_size(array);
|
|
1744
|
+
hb_array_T* new_array = hb_array_init(old_size + 1, context->allocator);
|
|
1745
|
+
|
|
1746
|
+
for (size_t j = 0; j < old_size; j++) {
|
|
1747
|
+
if (j == i) {
|
|
1748
|
+
hb_array_append(new_array, replacement);
|
|
1749
|
+
hb_array_append(new_array, trailing_text);
|
|
1750
|
+
} else {
|
|
1751
|
+
hb_array_append(new_array, hb_array_get(array, j));
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
array->items = new_array->items;
|
|
1756
|
+
array->size = new_array->size;
|
|
1757
|
+
array->capacity = new_array->capacity;
|
|
1758
|
+
i++;
|
|
1759
|
+
continue;
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
hb_array_set(array, i, replacement);
|
|
1054
1765
|
}
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
void transform_tag_helper_blocks(const AST_NODE_T* node, analyze_ruby_context_T* context) {
|
|
1770
|
+
if (!node || !context) { return; }
|
|
1055
1771
|
|
|
1056
|
-
|
|
1772
|
+
switch (node->type) {
|
|
1773
|
+
case AST_DOCUMENT_NODE: transform_tag_helper_array(((AST_DOCUMENT_NODE_T*) node)->children, context); break;
|
|
1774
|
+
case AST_HTML_ELEMENT_NODE: transform_tag_helper_array(((AST_HTML_ELEMENT_NODE_T*) node)->body, context); break;
|
|
1775
|
+
case AST_HTML_CONDITIONAL_ELEMENT_NODE:
|
|
1776
|
+
transform_tag_helper_array(((AST_HTML_CONDITIONAL_ELEMENT_NODE_T*) node)->body, context);
|
|
1777
|
+
break;
|
|
1778
|
+
case AST_HTML_OPEN_TAG_NODE:
|
|
1779
|
+
transform_tag_helper_array(((AST_HTML_OPEN_TAG_NODE_T*) node)->children, context);
|
|
1780
|
+
break;
|
|
1781
|
+
case AST_HTML_ATTRIBUTE_VALUE_NODE:
|
|
1782
|
+
transform_tag_helper_array(((AST_HTML_ATTRIBUTE_VALUE_NODE_T*) node)->children, context);
|
|
1783
|
+
break;
|
|
1784
|
+
case AST_ERB_BLOCK_NODE: transform_tag_helper_array(((AST_ERB_BLOCK_NODE_T*) node)->body, context); break;
|
|
1785
|
+
case AST_ERB_IF_NODE: transform_tag_helper_array(((AST_ERB_IF_NODE_T*) node)->statements, context); break;
|
|
1786
|
+
case AST_ERB_ELSE_NODE: transform_tag_helper_array(((AST_ERB_ELSE_NODE_T*) node)->statements, context); break;
|
|
1787
|
+
case AST_ERB_UNLESS_NODE: transform_tag_helper_array(((AST_ERB_UNLESS_NODE_T*) node)->statements, context); break;
|
|
1788
|
+
case AST_ERB_CASE_NODE:
|
|
1789
|
+
transform_tag_helper_array(((AST_ERB_CASE_NODE_T*) node)->children, context);
|
|
1790
|
+
transform_tag_helper_array(((AST_ERB_CASE_NODE_T*) node)->conditions, context);
|
|
1791
|
+
break;
|
|
1792
|
+
case AST_ERB_CASE_MATCH_NODE:
|
|
1793
|
+
transform_tag_helper_array(((AST_ERB_CASE_MATCH_NODE_T*) node)->children, context);
|
|
1794
|
+
transform_tag_helper_array(((AST_ERB_CASE_MATCH_NODE_T*) node)->conditions, context);
|
|
1795
|
+
break;
|
|
1796
|
+
case AST_ERB_WHEN_NODE: transform_tag_helper_array(((AST_ERB_WHEN_NODE_T*) node)->statements, context); break;
|
|
1797
|
+
case AST_ERB_WHILE_NODE: transform_tag_helper_array(((AST_ERB_WHILE_NODE_T*) node)->statements, context); break;
|
|
1798
|
+
case AST_ERB_UNTIL_NODE: transform_tag_helper_array(((AST_ERB_UNTIL_NODE_T*) node)->statements, context); break;
|
|
1799
|
+
case AST_ERB_FOR_NODE: transform_tag_helper_array(((AST_ERB_FOR_NODE_T*) node)->statements, context); break;
|
|
1800
|
+
case AST_ERB_BEGIN_NODE: transform_tag_helper_array(((AST_ERB_BEGIN_NODE_T*) node)->statements, context); break;
|
|
1801
|
+
case AST_ERB_RESCUE_NODE: transform_tag_helper_array(((AST_ERB_RESCUE_NODE_T*) node)->statements, context); break;
|
|
1802
|
+
case AST_ERB_ENSURE_NODE: transform_tag_helper_array(((AST_ERB_ENSURE_NODE_T*) node)->statements, context); break;
|
|
1803
|
+
case AST_ERB_IN_NODE: transform_tag_helper_array(((AST_ERB_IN_NODE_T*) node)->statements, context); break;
|
|
1804
|
+
default: break;
|
|
1057
1805
|
}
|
|
1058
1806
|
}
|
|
1059
1807
|
|