herb 0.9.5-arm-linux-gnu → 0.9.7-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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/ext/herb/extension.c +8 -0
  3. data/ext/herb/extension_helpers.c +1 -0
  4. data/lib/herb/3.0/herb.so +0 -0
  5. data/lib/herb/3.1/herb.so +0 -0
  6. data/lib/herb/3.2/herb.so +0 -0
  7. data/lib/herb/3.3/herb.so +0 -0
  8. data/lib/herb/3.4/herb.so +0 -0
  9. data/lib/herb/4.0/herb.so +0 -0
  10. data/lib/herb/action_view/helper_registry.rb +8107 -0
  11. data/lib/herb/parser_options.rb +7 -2
  12. data/lib/herb/project.rb +2 -5
  13. data/lib/herb/version.rb +1 -1
  14. data/sig/herb/action_view/helper_registry.rbs +1144 -0
  15. data/sig/herb/parser_options.rbs +6 -2
  16. data/src/analyze/action_view/generated_handlers.c +355 -0
  17. data/src/analyze/action_view/generated_handlers.h +16 -0
  18. data/src/analyze/action_view/helper_registry.c +7244 -0
  19. data/src/analyze/action_view/image_tag.c +4 -31
  20. data/src/analyze/action_view/javascript_include_tag.c +1 -42
  21. data/src/analyze/action_view/javascript_tag.c +0 -52
  22. data/src/analyze/action_view/registry.c +2 -2
  23. data/src/analyze/action_view/tag_helpers.c +8 -120
  24. data/src/analyze/action_view/turbo_frame_tag.c +1 -36
  25. data/src/analyze/analyze.c +7 -0
  26. data/src/analyze/postfix_conditionals.c +326 -0
  27. data/src/analyze/ternary_conditionals.c +265 -0
  28. data/src/include/analyze/action_view/helper_registry.h +325 -0
  29. data/src/include/analyze/action_view/tag_helpers.h +0 -1
  30. data/src/include/analyze/postfix_conditionals.h +9 -0
  31. data/src/include/analyze/ternary_conditionals.h +15 -0
  32. data/src/include/parser/parser.h +1 -0
  33. data/src/include/version.h +1 -1
  34. data/src/parser.c +1 -0
  35. data/templates/java/org/herb/ast/HelperRegistry.java.erb +258 -0
  36. data/templates/javascript/packages/core/src/action-view-helpers.ts.erb +171 -0
  37. data/templates/javascript/packages/core/src/nodes.ts.erb +5 -1
  38. data/templates/lib/herb/action_view/helper_registry.rb.erb +288 -0
  39. data/templates/rust/src/action_view_helpers.rs.erb +154 -0
  40. data/templates/src/analyze/action_view/generated_handlers.c.erb +230 -0
  41. data/templates/src/analyze/action_view/generated_handlers.h.erb +12 -0
  42. data/templates/src/analyze/action_view/helper_registry.c.erb +114 -0
  43. data/templates/src/include/analyze/action_view/helper_registry.h.erb +82 -0
  44. data/templates/template.rb +338 -1
  45. metadata +19 -3
  46. data/src/analyze/action_view/content_tag.c +0 -78
  47. data/src/analyze/action_view/tag.c +0 -87
@@ -0,0 +1,230 @@
1
+ #include "../../include/analyze/action_view/tag_helper_handler.h"
2
+ #include "../../include/lib/hb_allocator.h"
3
+ #include "../../include/lib/hb_string.h"
4
+
5
+ #include <prism.h>
6
+ #include <stdbool.h>
7
+ #include <string.h>
8
+
9
+ <%- supported_helpers = helpers.select(&:supported?).reject(&:custom_transform?) -%>
10
+ // ==========================================================================
11
+ // Generated detect functions
12
+ // ==========================================================================
13
+ <%- supported_helpers.each do |helper| -%>
14
+ <%- if helper.call_name_detect? -%>
15
+
16
+ bool detect_<%= helper.safe_name %>(pm_call_node_t* call_node, pm_parser_t* parser) {
17
+ if (!call_node || !call_node->name) { return false; }
18
+
19
+ pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, call_node->name);
20
+
21
+ return constant && constant->length == <%= helper.name.length %> && strncmp((const char*) constant->start, "<%= helper.name %>", <%= helper.name.length %>) == 0;
22
+ }
23
+ <%- elsif helper.receiver_call_detect? -%>
24
+
25
+ bool detect_<%= helper.safe_name %>(pm_call_node_t* call_node, pm_parser_t* parser) {
26
+ if (!call_node || !call_node->receiver) { return false; }
27
+ if (call_node->receiver->type != PM_CALL_NODE) { return false; }
28
+
29
+ pm_call_node_t* receiver_node = (pm_call_node_t*) call_node->receiver;
30
+ if (!receiver_node->name) { return false; }
31
+
32
+ pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, receiver_node->name);
33
+
34
+ return constant && constant->length == 3 && strncmp((const char*) constant->start, "tag", 3) == 0;
35
+ }
36
+ <%- end -%>
37
+ <%- end -%>
38
+
39
+ // ==========================================================================
40
+ // Generated extract_tag_name functions
41
+ // ==========================================================================
42
+ <%- supported_helpers.each do |helper| -%>
43
+ <%- if helper.tag_name -%>
44
+
45
+ static char* extract_<%= helper.safe_name %>_tag_name(pm_call_node_t* _call_node, pm_parser_t* _parser, hb_allocator_T* allocator) {
46
+ (void) _call_node;
47
+ (void) _parser;
48
+
49
+ return hb_allocator_strdup(allocator, "<%= helper.tag_name %>");
50
+ }
51
+ <%- elsif helper.name == "content_tag" -%>
52
+
53
+ static char* extract_<%= helper.safe_name %>_tag_name(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator) {
54
+ (void) parser;
55
+
56
+ if (!call_node || !call_node->arguments) { return NULL; }
57
+
58
+ pm_arguments_node_t* arguments = call_node->arguments;
59
+ if (!arguments->arguments.size) { return NULL; }
60
+
61
+ pm_node_t* first_argument = arguments->arguments.nodes[0];
62
+
63
+ if (first_argument->type == PM_STRING_NODE) {
64
+ pm_string_node_t* string_node = (pm_string_node_t*) first_argument;
65
+ size_t length = pm_string_length(&string_node->unescaped);
66
+ return hb_allocator_strndup(allocator, (const char*) pm_string_source(&string_node->unescaped), length);
67
+ } else if (first_argument->type == PM_SYMBOL_NODE) {
68
+ pm_symbol_node_t* symbol_node = (pm_symbol_node_t*) first_argument;
69
+ size_t length = pm_string_length(&symbol_node->unescaped);
70
+ return hb_allocator_strndup(allocator, (const char*) pm_string_source(&symbol_node->unescaped), length);
71
+ }
72
+
73
+ return NULL;
74
+ }
75
+ <%- elsif helper.name == "tag" -%>
76
+
77
+ extern bool is_ruby_introspection_method(hb_string_T method_name);
78
+
79
+ static char* extract_<%= helper.safe_name %>_tag_name(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator) {
80
+ if (!call_node || !call_node->name) { return NULL; }
81
+
82
+ pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, call_node->name);
83
+ if (!constant) { return NULL; }
84
+
85
+ if (is_ruby_introspection_method(hb_string_from_data((const char*) constant->start, constant->length))) { return NULL; }
86
+
87
+ char* name = hb_allocator_strndup(allocator, (const char*) constant->start, constant->length);
88
+
89
+ for (size_t i = 0; i < constant->length && name[i] != '\0'; i++) {
90
+ if (name[i] == '_') { name[i] = '-'; }
91
+ }
92
+
93
+ return name;
94
+ }
95
+ <%- end -%>
96
+ <%- end -%>
97
+
98
+ // ==========================================================================
99
+ // Generated extract_content functions
100
+ // ==========================================================================
101
+ <%- supported_helpers.each do |helper| -%>
102
+ <%- content = helper.content -%>
103
+ <%- if content.nil? -%>
104
+
105
+ static char* extract_<%= helper.safe_name %>_content(pm_call_node_t* _call_node, pm_parser_t* _parser, hb_allocator_T* _allocator) {
106
+ (void) _call_node;
107
+ (void) _parser;
108
+ (void) _allocator;
109
+
110
+ return NULL;
111
+ }
112
+ <%- elsif content.first_arg? -%>
113
+
114
+ static char* extract_<%= helper.safe_name %>_content(pm_call_node_t* call_node, pm_parser_t* _parser, hb_allocator_T* allocator) {
115
+ (void) _parser;
116
+
117
+ if (!call_node || !call_node->arguments) { return NULL; }
118
+
119
+ pm_arguments_node_t* arguments = call_node->arguments;
120
+ if (!arguments->arguments.size) { return NULL; }
121
+
122
+ pm_node_t* first_argument = arguments->arguments.nodes[0];
123
+
124
+ <%- if content.skip_if_hash -%>
125
+ if (first_argument->type == PM_KEYWORD_HASH_NODE) { return NULL; }
126
+ <%- end -%>
127
+
128
+ if (first_argument->type == PM_STRING_NODE) {
129
+ pm_string_node_t* string_node = (pm_string_node_t*) first_argument;
130
+ size_t length = pm_string_length(&string_node->unescaped);
131
+ return hb_allocator_strndup(allocator, (const char*) pm_string_source(&string_node->unescaped), length);
132
+ }
133
+
134
+ size_t source_length = first_argument->location.end - first_argument->location.start;
135
+ return hb_allocator_strndup(allocator, (const char*) first_argument->location.start, source_length);
136
+ }
137
+ <%- elsif content.block_or_arg? -%>
138
+
139
+ static char* extract_<%= helper.safe_name %>_content(pm_call_node_t* call_node, pm_parser_t* <%= helper.receiver_call_detect? ? "parser" : "_parser" %>, hb_allocator_T* allocator) {
140
+ (void) <%= helper.receiver_call_detect? ? "parser" : "_parser" %>;
141
+
142
+ if (!call_node) { return NULL; }
143
+
144
+ <%- if helper.receiver_call_detect? -%>
145
+ if (call_node->name) {
146
+ pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, call_node->name);
147
+
148
+ if (constant && is_ruby_introspection_method(hb_string_from_data((const char*) constant->start, constant->length))) {
149
+ return NULL;
150
+ }
151
+ }
152
+ <%- end -%>
153
+
154
+ char* block_content = extract_inline_block_content(call_node, allocator);
155
+ if (block_content) { return block_content; }
156
+
157
+ <%- arg_index = (content.arg_position || 1) - 1 -%>
158
+
159
+ <%- if content.arg_position -%>
160
+ if (call_node->arguments) {
161
+ pm_arguments_node_t* arguments = call_node->arguments;
162
+
163
+ if (arguments->arguments.size >= <%= content.arg_position %>) {
164
+ pm_node_t* argument = arguments->arguments.nodes[<%= arg_index %>];
165
+
166
+ <%- if content.skip_if_hash -%>
167
+ if (argument->type != PM_KEYWORD_HASH_NODE) {
168
+ <%- end -%>
169
+
170
+ if (argument->type == PM_STRING_NODE) {
171
+ pm_string_node_t* string_node = (pm_string_node_t*) argument;
172
+ size_t length = pm_string_length(&string_node->unescaped);
173
+ return hb_allocator_strndup(allocator, (const char*) pm_string_source(&string_node->unescaped), length);
174
+ }
175
+
176
+ size_t source_length = argument->location.end - argument->location.start;
177
+
178
+ <%- if content.to_s_suffix_when_single -%>
179
+ if (arguments->arguments.size == 1 && argument->type != PM_NIL_NODE) {
180
+ const char* suffix = ".to_s";
181
+ size_t suffix_length = strlen(suffix);
182
+ size_t total_length = source_length + suffix_length;
183
+ char* ruby_expression = hb_allocator_alloc(allocator, total_length + 1);
184
+
185
+ memcpy(ruby_expression, (const char*) argument->location.start, source_length);
186
+ memcpy(ruby_expression + source_length, suffix, suffix_length);
187
+ ruby_expression[total_length] = '\0';
188
+
189
+ return ruby_expression;
190
+ }
191
+ <%- end -%>
192
+
193
+ return hb_allocator_strndup(allocator, (const char*) argument->location.start, source_length);
194
+
195
+ <%- if content.skip_if_hash -%>
196
+ }
197
+ <%- end -%>
198
+ }
199
+ }
200
+ <%- end -%>
201
+
202
+ return NULL;
203
+ }
204
+ <%- end -%>
205
+ <%- end -%>
206
+
207
+ // ==========================================================================
208
+ // Generated supports_block functions
209
+ // ==========================================================================
210
+ <%- supported_helpers.each do |helper| -%>
211
+
212
+ static bool <%= helper.safe_name %>_supports_block(void) {
213
+ return <%= helper.supports_block %>;
214
+ }
215
+ <%- end -%>
216
+
217
+ // ==========================================================================
218
+ // Generated handler structs
219
+ // ==========================================================================
220
+ <%- supported_helpers.each do |helper| -%>
221
+
222
+ const tag_helper_handler_T <%= helper.safe_name %>_handler = {
223
+ .name = "<%= helper.name %>",
224
+ .source = HB_STRING_LITERAL("<%= helper.source %>"),
225
+ .detect = detect_<%= helper.safe_name %>,
226
+ .extract_tag_name = extract_<%= helper.safe_name %>_tag_name,
227
+ .extract_content = extract_<%= helper.safe_name %>_content,
228
+ .supports_block = <%= helper.safe_name %>_supports_block,
229
+ };
230
+ <%- end -%>
@@ -0,0 +1,12 @@
1
+ #ifndef GENERATED_HANDLERS_H
2
+ #define GENERATED_HANDLERS_H
3
+
4
+ #include "../../include/analyze/action_view/tag_helper_handler.h"
5
+
6
+ <%- supported_helpers = helpers.select(&:supported?) -%>
7
+ <%- supported_helpers.each do |helper| -%>
8
+ <%- next if helper.custom_transform? -%>
9
+ extern const tag_helper_handler_T <%= helper.safe_name %>_handler;
10
+ <%- end -%>
11
+
12
+ #endif
@@ -0,0 +1,114 @@
1
+ #include "../../include/analyze/action_view/helper_registry.h"
2
+ #include "../../include/lib/hb_string.h"
3
+
4
+ #include <string.h>
5
+
6
+ <%- helpers.each do |helper| -%>
7
+ <%- if helper.implicit_attribute? -%>
8
+ static const helper_implicit_attribute_T <%= helper.safe_name %>_implicit_attribute = {
9
+ .name = "<%= helper.implicit_attribute.name %>",
10
+ .source = "<%= helper.implicit_attribute.source %>",
11
+ <%- if helper.implicit_attribute.source_with_block -%>
12
+ .source_with_block = "<%= helper.implicit_attribute.source_with_block %>",
13
+ <%- else -%>
14
+ .source_with_block = NULL,
15
+ <%- end -%>
16
+ .wrapper = "<%= helper.implicit_attribute.wrapper %>",
17
+ };
18
+
19
+ <%- end -%>
20
+ <%- if helper.arguments.any? -%>
21
+ static const helper_argument_T <%= helper.safe_name %>_arguments[] = {
22
+ <%- helper.arguments.each do |arg| -%>
23
+ { .name = "<%= arg.name %>", .type = "<%= arg.type_display %>", .description = "<%= arg.escaped_description %>" },
24
+ <%- end -%>
25
+ };
26
+
27
+ <%- end -%>
28
+ <%- if helper.options.any? -%>
29
+ static const helper_option_T <%= helper.safe_name %>_options[] = {
30
+ <%- helper.options.each do |opt| -%>
31
+ { .name = "<%= opt.name %>", .type = "<%= opt.type_display %>", .maps_to = <%= opt.maps_to ? "\"#{opt.maps_to}\"" : "NULL" %>, .description = "<%= opt.escaped_description %>" },
32
+ <%- end -%>
33
+ };
34
+
35
+ <%- end -%>
36
+ <%- end -%>
37
+ static const helper_registry_entry_T registry_entries[HELPER_COUNT] = {
38
+ <%- helpers.each do |helper| -%>
39
+ {
40
+ .type = HELPER_<%= helper.constant_name %>,
41
+ .name = "<%= helper.name %>",
42
+ .name_length = <%= helper.name.length %>,
43
+ .source = HB_STRING_LITERAL("<%= helper.source %>"),
44
+ .gem = "<%= helper.gem %>",
45
+ .output = HELPER_OUTPUT_<%= helper.output.upcase %>,
46
+ .visibility = "<%= helper.visibility %>",
47
+ .tag_name = <%= helper.tag_name ? "\"#{helper.tag_name}\"" : "NULL" %>,
48
+ .is_void = <%= helper.void? %>,
49
+ .supports_block = <%= helper.supports_block %>,
50
+ .preferred_for_tag = <%= helper.preferred_for_tag %>,
51
+ .supported = <%= helper.supported %>,
52
+ .detect_style = <%= helper.call_name_detect? ? "HELPER_DETECT_CALL_NAME" : "HELPER_DETECT_RECEIVER_CALL" %>,
53
+ .description = "<%= helper.escaped_description %>",
54
+ .signature = "<%= helper.escaped_signature %>",
55
+ .documentation_url = "<%= helper.documentation_url %>",
56
+ .implicit_attribute = <%= helper.implicit_attribute? ? "&#{helper.safe_name}_implicit_attribute" : "NULL" %>,
57
+ .arguments = <%= helper.arguments.any? ? "#{helper.safe_name}_arguments" : "NULL" %>,
58
+ .arguments_count = <%= helper.arguments.size %>,
59
+ .options = <%= helper.options.any? ? "#{helper.safe_name}_options" : "NULL" %>,
60
+ .options_count = <%= helper.options.size %>,
61
+ },
62
+ <%- end -%>
63
+ };
64
+
65
+ const helper_registry_entry_T* helper_registry_get(helper_type_T type) {
66
+ if (type < 0 || type >= HELPER_COUNT) { return NULL; }
67
+
68
+ return &registry_entries[type];
69
+ }
70
+
71
+ const helper_registry_entry_T* helper_registry_find_by_name(const char* name, size_t length) {
72
+ for (size_t i = 0; i < HELPER_COUNT; i++) {
73
+ if (registry_entries[i].name_length == length && strncmp(registry_entries[i].name, name, length) == 0) {
74
+ return &registry_entries[i];
75
+ }
76
+ }
77
+
78
+ return NULL;
79
+ }
80
+
81
+ const helper_registry_entry_T* helper_registry_find_by_source(const char* source) {
82
+ if (!source) { return NULL; }
83
+
84
+ size_t source_length = strlen(source);
85
+
86
+ for (size_t i = 0; i < HELPER_COUNT; i++) {
87
+ if (registry_entries[i].source.length == source_length && strncmp(registry_entries[i].source.data, source, source_length) == 0) {
88
+ return &registry_entries[i];
89
+ }
90
+ }
91
+
92
+ return NULL;
93
+ }
94
+
95
+ const helper_registry_entry_T* helper_registry_find_preferred_for_tag(const char* tag_name) {
96
+ if (!tag_name) { return NULL; }
97
+
98
+ for (size_t i = 0; i < HELPER_COUNT; i++) {
99
+ if (registry_entries[i].tag_name && registry_entries[i].preferred_for_tag
100
+ && strcmp(registry_entries[i].tag_name, tag_name) == 0) {
101
+ return &registry_entries[i];
102
+ }
103
+ }
104
+
105
+ return NULL;
106
+ }
107
+
108
+ const helper_registry_entry_T* helper_registry_entries(void) {
109
+ return registry_entries;
110
+ }
111
+
112
+ size_t helper_registry_count(void) {
113
+ return HELPER_COUNT;
114
+ }
@@ -0,0 +1,82 @@
1
+ #ifndef HELPER_REGISTRY_H
2
+ #define HELPER_REGISTRY_H
3
+
4
+ #include "../../lib/hb_string.h"
5
+
6
+ #include <stdbool.h>
7
+ #include <stddef.h>
8
+
9
+ typedef enum {
10
+ <%- helpers.each do |helper| -%>
11
+ HELPER_<%= helper.constant_name %>,
12
+ <%- end -%>
13
+ } helper_type_T;
14
+
15
+ #define HELPER_COUNT <%= helpers.size %>
16
+
17
+ typedef enum {
18
+ HELPER_DETECT_CALL_NAME,
19
+ HELPER_DETECT_RECEIVER_CALL,
20
+ } helper_detect_style_T;
21
+
22
+ typedef struct {
23
+ const char* name;
24
+ const char* type;
25
+ const char* description;
26
+ } helper_argument_T;
27
+
28
+ typedef struct {
29
+ const char* name;
30
+ const char* type;
31
+ const char* maps_to;
32
+ const char* description;
33
+ } helper_option_T;
34
+
35
+ typedef struct {
36
+ const char* name;
37
+ const char* source;
38
+ const char* source_with_block;
39
+ const char* wrapper;
40
+ } helper_implicit_attribute_T;
41
+
42
+ typedef enum {
43
+ HELPER_OUTPUT_HTML,
44
+ HELPER_OUTPUT_TEXT,
45
+ HELPER_OUTPUT_URL,
46
+ HELPER_OUTPUT_BOOLEAN,
47
+ HELPER_OUTPUT_VOID,
48
+ HELPER_OUTPUT_OBJECT,
49
+ } helper_output_T;
50
+
51
+ typedef struct {
52
+ helper_type_T type;
53
+ const char* name;
54
+ size_t name_length;
55
+ hb_string_T source;
56
+ const char* gem;
57
+ helper_output_T output;
58
+ const char* visibility;
59
+ const char* tag_name;
60
+ bool is_void;
61
+ bool supports_block;
62
+ bool preferred_for_tag;
63
+ bool supported;
64
+ helper_detect_style_T detect_style;
65
+ const char* description;
66
+ const char* signature;
67
+ const char* documentation_url;
68
+ const helper_implicit_attribute_T* implicit_attribute;
69
+ const helper_argument_T* arguments;
70
+ size_t arguments_count;
71
+ const helper_option_T* options;
72
+ size_t options_count;
73
+ } helper_registry_entry_T;
74
+
75
+ const helper_registry_entry_T* helper_registry_get(helper_type_T type);
76
+ const helper_registry_entry_T* helper_registry_find_by_name(const char* name, size_t length);
77
+ const helper_registry_entry_T* helper_registry_find_by_source(const char* source);
78
+ const helper_registry_entry_T* helper_registry_find_preferred_for_tag(const char* tag_name);
79
+ const helper_registry_entry_T* helper_registry_entries(void);
80
+ size_t helper_registry_count(void);
81
+
82
+ #endif