herb 0.9.4-arm-linux-gnu → 0.9.6-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/config.yml +57 -21
- data/ext/herb/extension.c +8 -0
- data/ext/herb/extension_helpers.c +1 -0
- data/ext/herb/nodes.c +93 -55
- 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/action_view/helper_registry.rb +8107 -0
- data/lib/herb/ast/nodes.rb +212 -78
- data/lib/herb/engine/compiler.rb +4 -6
- data/lib/herb/parser_options.rb +7 -2
- data/lib/herb/project.rb +2 -5
- data/lib/herb/version.rb +1 -1
- data/lib/herb/visitor.rb +8 -2
- data/sig/herb/action_view/helper_registry.rbs +1144 -0
- data/sig/herb/ast/nodes.rbs +85 -34
- data/sig/herb/parser_options.rbs +6 -2
- data/sig/herb/visitor.rbs +5 -2
- data/sig/serialized_ast_nodes.rbs +20 -9
- data/src/analyze/action_view/generated_handlers.c +355 -0
- data/src/analyze/action_view/generated_handlers.h +16 -0
- data/src/analyze/action_view/helper_registry.c +7244 -0
- data/src/analyze/action_view/image_tag.c +4 -31
- data/src/analyze/action_view/javascript_include_tag.c +1 -42
- data/src/analyze/action_view/javascript_tag.c +26 -40
- data/src/analyze/action_view/registry.c +2 -2
- data/src/analyze/action_view/tag_helper_node_builders.c +23 -2
- data/src/analyze/action_view/tag_helpers.c +61 -134
- data/src/analyze/action_view/turbo_frame_tag.c +1 -36
- data/src/analyze/analyze.c +28 -0
- data/src/analyze/analyze_helpers.c +406 -0
- data/src/analyze/builders.c +1 -0
- data/src/analyze/missing_end.c +16 -0
- data/src/analyze/parse_errors.c +3 -2
- data/src/analyze/postfix_conditionals.c +326 -0
- data/src/analyze/render_nodes.c +231 -35
- data/src/analyze/strict_locals.c +22 -338
- data/src/analyze/ternary_conditionals.c +265 -0
- data/src/analyze/transform.c +23 -2
- data/src/ast/ast_nodes.c +114 -57
- data/src/ast/ast_pretty_print.c +109 -25
- data/src/include/analyze/action_view/helper_registry.h +325 -0
- data/src/include/analyze/action_view/tag_helper_handler.h +3 -0
- data/src/include/analyze/action_view/tag_helper_node_builders.h +7 -0
- data/src/include/analyze/action_view/tag_helpers.h +0 -1
- data/src/include/analyze/helpers.h +18 -0
- data/src/include/analyze/postfix_conditionals.h +9 -0
- data/src/include/analyze/ternary_conditionals.h +15 -0
- data/src/include/ast/ast_nodes.h +27 -13
- data/src/include/parser/parser.h +1 -0
- data/src/include/version.h +1 -1
- data/src/parser/match_tags.c +37 -6
- data/src/parser.c +9 -0
- data/src/visitor.c +50 -7
- data/templates/java/org/herb/ast/HelperRegistry.java.erb +258 -0
- data/templates/javascript/packages/core/src/action-view-helpers.ts.erb +171 -0
- data/templates/javascript/packages/core/src/nodes.ts.erb +5 -1
- data/templates/lib/herb/action_view/helper_registry.rb.erb +288 -0
- data/templates/rust/src/action_view_helpers.rs.erb +154 -0
- data/templates/src/analyze/action_view/generated_handlers.c.erb +230 -0
- data/templates/src/analyze/action_view/generated_handlers.h.erb +12 -0
- data/templates/src/analyze/action_view/helper_registry.c.erb +114 -0
- data/templates/src/include/analyze/action_view/helper_registry.h.erb +82 -0
- data/templates/template.rb +338 -1
- metadata +19 -3
- data/src/analyze/action_view/content_tag.c +0 -78
- data/src/analyze/action_view/tag.c +0 -87
data/src/visitor.c
CHANGED
|
@@ -237,6 +237,12 @@ void herb_visit_child_nodes(const AST_NODE_T *node, bool (*visitor)(const AST_NO
|
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
if (erb_block_node->block_arguments != NULL) {
|
|
241
|
+
for (size_t index = 0; index < hb_array_size(erb_block_node->block_arguments); index++) {
|
|
242
|
+
herb_visit_node(hb_array_get(erb_block_node->block_arguments, index), visitor, data);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
240
246
|
if (erb_block_node->rescue_clause != NULL) {
|
|
241
247
|
herb_visit_node((AST_NODE_T *) erb_block_node->rescue_clause, visitor, data);
|
|
242
248
|
}
|
|
@@ -442,22 +448,59 @@ void herb_visit_child_nodes(const AST_NODE_T *node, bool (*visitor)(const AST_NO
|
|
|
442
448
|
|
|
443
449
|
} break;
|
|
444
450
|
|
|
451
|
+
case AST_RUBY_RENDER_KEYWORDS_NODE: {
|
|
452
|
+
const AST_RUBY_RENDER_KEYWORDS_NODE_T* ruby_render_keywords_node = ((const AST_RUBY_RENDER_KEYWORDS_NODE_T *) node);
|
|
453
|
+
|
|
454
|
+
if (ruby_render_keywords_node->locals != NULL) {
|
|
455
|
+
for (size_t index = 0; index < hb_array_size(ruby_render_keywords_node->locals); index++) {
|
|
456
|
+
herb_visit_node(hb_array_get(ruby_render_keywords_node->locals, index), visitor, data);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
} break;
|
|
461
|
+
|
|
445
462
|
case AST_ERB_RENDER_NODE: {
|
|
446
463
|
const AST_ERB_RENDER_NODE_T* erb_render_node = ((const AST_ERB_RENDER_NODE_T *) node);
|
|
447
464
|
|
|
448
|
-
if (erb_render_node->
|
|
449
|
-
|
|
450
|
-
|
|
465
|
+
if (erb_render_node->keywords != NULL) {
|
|
466
|
+
herb_visit_node((AST_NODE_T *) erb_render_node->keywords, visitor, data);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (erb_render_node->body != NULL) {
|
|
470
|
+
for (size_t index = 0; index < hb_array_size(erb_render_node->body); index++) {
|
|
471
|
+
herb_visit_node(hb_array_get(erb_render_node->body, index), visitor, data);
|
|
451
472
|
}
|
|
452
473
|
}
|
|
453
474
|
|
|
475
|
+
if (erb_render_node->block_arguments != NULL) {
|
|
476
|
+
for (size_t index = 0; index < hb_array_size(erb_render_node->block_arguments); index++) {
|
|
477
|
+
herb_visit_node(hb_array_get(erb_render_node->block_arguments, index), visitor, data);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (erb_render_node->rescue_clause != NULL) {
|
|
482
|
+
herb_visit_node((AST_NODE_T *) erb_render_node->rescue_clause, visitor, data);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (erb_render_node->else_clause != NULL) {
|
|
486
|
+
herb_visit_node((AST_NODE_T *) erb_render_node->else_clause, visitor, data);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if (erb_render_node->ensure_clause != NULL) {
|
|
490
|
+
herb_visit_node((AST_NODE_T *) erb_render_node->ensure_clause, visitor, data);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (erb_render_node->end_node != NULL) {
|
|
494
|
+
herb_visit_node((AST_NODE_T *) erb_render_node->end_node, visitor, data);
|
|
495
|
+
}
|
|
496
|
+
|
|
454
497
|
} break;
|
|
455
498
|
|
|
456
|
-
case
|
|
457
|
-
const
|
|
499
|
+
case AST_RUBY_PARAMETER_NODE: {
|
|
500
|
+
const AST_RUBY_PARAMETER_NODE_T* ruby_parameter_node = ((const AST_RUBY_PARAMETER_NODE_T *) node);
|
|
458
501
|
|
|
459
|
-
if (
|
|
460
|
-
herb_visit_node((AST_NODE_T *)
|
|
502
|
+
if (ruby_parameter_node->default_value != NULL) {
|
|
503
|
+
herb_visit_node((AST_NODE_T *) ruby_parameter_node->default_value, visitor, data);
|
|
461
504
|
}
|
|
462
505
|
|
|
463
506
|
} break;
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
package org.herb.ast;
|
|
2
|
+
|
|
3
|
+
import java.util.Collections;
|
|
4
|
+
import java.util.LinkedHashMap;
|
|
5
|
+
import java.util.List;
|
|
6
|
+
import java.util.Map;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Type enum for all supported Action View tag helpers.
|
|
10
|
+
*/
|
|
11
|
+
public enum HelperType {
|
|
12
|
+
<%- helpers.each_with_index do |helper, index| -%>
|
|
13
|
+
<%= helper.constant_name %>("<%= helper.name %>")<%= index < helpers.size - 1 ? "," : ";" %>
|
|
14
|
+
<%- end -%>
|
|
15
|
+
|
|
16
|
+
private final String name;
|
|
17
|
+
|
|
18
|
+
HelperType(String name) {
|
|
19
|
+
this.name = name;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public String getName() {
|
|
23
|
+
return name;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public static HelperType fromName(String name) {
|
|
27
|
+
for (HelperType type : values()) {
|
|
28
|
+
if (type.name.equals(name)) {
|
|
29
|
+
return type;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Argument metadata for a tag helper.
|
|
38
|
+
*/
|
|
39
|
+
class HelperArgument {
|
|
40
|
+
private final String name;
|
|
41
|
+
private final int position;
|
|
42
|
+
private final String type;
|
|
43
|
+
private final boolean optional;
|
|
44
|
+
private final String defaultValue;
|
|
45
|
+
private final boolean splat;
|
|
46
|
+
private final String description;
|
|
47
|
+
|
|
48
|
+
HelperArgument(String name, int position, String type, boolean optional, String defaultValue, boolean splat, String description) {
|
|
49
|
+
this.name = name;
|
|
50
|
+
this.position = position;
|
|
51
|
+
this.type = type;
|
|
52
|
+
this.optional = optional;
|
|
53
|
+
this.defaultValue = defaultValue;
|
|
54
|
+
this.splat = splat;
|
|
55
|
+
this.description = description;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public String getName() { return name; }
|
|
59
|
+
public int getPosition() { return position; }
|
|
60
|
+
public String getType() { return type; }
|
|
61
|
+
public boolean isOptional() { return optional; }
|
|
62
|
+
public String getDefaultValue() { return defaultValue; }
|
|
63
|
+
public boolean isSplat() { return splat; }
|
|
64
|
+
public String getDescription() { return description; }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Option metadata for a tag helper.
|
|
69
|
+
*/
|
|
70
|
+
class HelperOption {
|
|
71
|
+
private final String name;
|
|
72
|
+
private final String type;
|
|
73
|
+
private final String mapsTo;
|
|
74
|
+
private final String description;
|
|
75
|
+
|
|
76
|
+
HelperOption(String name, String type, String mapsTo, String description) {
|
|
77
|
+
this.name = name;
|
|
78
|
+
this.type = type;
|
|
79
|
+
this.mapsTo = mapsTo;
|
|
80
|
+
this.description = description;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public String getName() { return name; }
|
|
84
|
+
public String getType() { return type; }
|
|
85
|
+
public String getMapsTo() { return mapsTo; }
|
|
86
|
+
public String getDescription() { return description; }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Implicit attribute metadata for a tag helper.
|
|
91
|
+
*/
|
|
92
|
+
class HelperImplicitAttribute {
|
|
93
|
+
private final String name;
|
|
94
|
+
private final String source;
|
|
95
|
+
private final String sourceWithBlock;
|
|
96
|
+
private final String wrapper;
|
|
97
|
+
|
|
98
|
+
HelperImplicitAttribute(String name, String source, String sourceWithBlock, String wrapper) {
|
|
99
|
+
this.name = name;
|
|
100
|
+
this.source = source;
|
|
101
|
+
this.sourceWithBlock = sourceWithBlock;
|
|
102
|
+
this.wrapper = wrapper;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
public String getName() { return name; }
|
|
106
|
+
public String getSource() { return source; }
|
|
107
|
+
public String getSourceWithBlock() { return sourceWithBlock; }
|
|
108
|
+
public String getWrapper() { return wrapper; }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Registry entry containing all metadata for a single tag helper.
|
|
113
|
+
*/
|
|
114
|
+
class HelperEntry {
|
|
115
|
+
private final String name;
|
|
116
|
+
private final HelperType type;
|
|
117
|
+
private final String source;
|
|
118
|
+
private final String gem;
|
|
119
|
+
private final String output;
|
|
120
|
+
private final String visibility;
|
|
121
|
+
private final String tagName;
|
|
122
|
+
private final boolean isVoid;
|
|
123
|
+
private final boolean supportsBlock;
|
|
124
|
+
private final boolean preferredForTag;
|
|
125
|
+
private final boolean supported;
|
|
126
|
+
private final String detectStyle;
|
|
127
|
+
private final String description;
|
|
128
|
+
private final String signature;
|
|
129
|
+
private final String documentationUrl;
|
|
130
|
+
private final HelperImplicitAttribute implicitAttribute;
|
|
131
|
+
private final List<HelperArgument> arguments;
|
|
132
|
+
private final List<HelperOption> options;
|
|
133
|
+
private final List<String> specialBehaviors;
|
|
134
|
+
private final List<String> aliases;
|
|
135
|
+
|
|
136
|
+
HelperEntry(
|
|
137
|
+
String name, HelperType type, String source, String gem, String output, String visibility, String tagName,
|
|
138
|
+
boolean isVoid, boolean supportsBlock, boolean preferredForTag, boolean supported, String detectStyle, String description,
|
|
139
|
+
String signature, String documentationUrl, HelperImplicitAttribute implicitAttribute,
|
|
140
|
+
List<HelperArgument> arguments, List<HelperOption> options, List<String> specialBehaviors, List<String> aliases
|
|
141
|
+
) {
|
|
142
|
+
this.name = name;
|
|
143
|
+
this.type = type;
|
|
144
|
+
this.source = source;
|
|
145
|
+
this.gem = gem;
|
|
146
|
+
this.output = output;
|
|
147
|
+
this.visibility = visibility;
|
|
148
|
+
this.tagName = tagName;
|
|
149
|
+
this.isVoid = isVoid;
|
|
150
|
+
this.supportsBlock = supportsBlock;
|
|
151
|
+
this.preferredForTag = preferredForTag;
|
|
152
|
+
this.supported = supported;
|
|
153
|
+
this.detectStyle = detectStyle;
|
|
154
|
+
this.description = description;
|
|
155
|
+
this.signature = signature;
|
|
156
|
+
this.documentationUrl = documentationUrl;
|
|
157
|
+
this.implicitAttribute = implicitAttribute;
|
|
158
|
+
this.arguments = arguments;
|
|
159
|
+
this.options = options;
|
|
160
|
+
this.specialBehaviors = specialBehaviors;
|
|
161
|
+
this.aliases = aliases;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public String getName() { return name; }
|
|
165
|
+
public HelperType getType() { return type; }
|
|
166
|
+
public String getSource() { return source; }
|
|
167
|
+
public String getGem() { return gem; }
|
|
168
|
+
public String getOutput() { return output; }
|
|
169
|
+
public String getVisibility() { return visibility; }
|
|
170
|
+
public String getTagName() { return tagName; }
|
|
171
|
+
public boolean isVoid() { return isVoid; }
|
|
172
|
+
public boolean supportsBlock() { return supportsBlock; }
|
|
173
|
+
public boolean isPreferredForTag() { return preferredForTag; }
|
|
174
|
+
public boolean isSupported() { return supported; }
|
|
175
|
+
public String getDetectStyle() { return detectStyle; }
|
|
176
|
+
public String getDescription() { return description; }
|
|
177
|
+
public String getSignature() { return signature; }
|
|
178
|
+
public String getDocumentationUrl() { return documentationUrl; }
|
|
179
|
+
public HelperImplicitAttribute getImplicitAttribute() { return implicitAttribute; }
|
|
180
|
+
public List<HelperArgument> getArguments() { return arguments; }
|
|
181
|
+
public List<HelperOption> getOptions() { return options; }
|
|
182
|
+
public List<String> getSpecialBehaviors() { return specialBehaviors; }
|
|
183
|
+
public List<String> getAliases() { return aliases; }
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Global registry of all supported Action View tag helpers.
|
|
188
|
+
*
|
|
189
|
+
* <p>Usage:
|
|
190
|
+
* <pre>
|
|
191
|
+
* HelperEntry entry = HelperRegistry.get("link_to");
|
|
192
|
+
* entry.supportsBlock(); // true
|
|
193
|
+
* entry.getTagName(); // "a"
|
|
194
|
+
* </pre>
|
|
195
|
+
*/
|
|
196
|
+
public final class HelperRegistry {
|
|
197
|
+
private static final Map<String, HelperEntry> BY_NAME;
|
|
198
|
+
private static final Map<String, HelperEntry> BY_SOURCE;
|
|
199
|
+
|
|
200
|
+
static {
|
|
201
|
+
Map<String, HelperEntry> byName = new LinkedHashMap<>();
|
|
202
|
+
Map<String, HelperEntry> bySource = new LinkedHashMap<>();
|
|
203
|
+
|
|
204
|
+
<%- helpers.each do |helper| -%>
|
|
205
|
+
{
|
|
206
|
+
HelperEntry entry = new HelperEntry(
|
|
207
|
+
"<%= helper.name %>",
|
|
208
|
+
HelperType.<%= helper.constant_name %>,
|
|
209
|
+
"<%= helper.source %>",
|
|
210
|
+
"<%= helper.gem %>",
|
|
211
|
+
"<%= helper.output %>",
|
|
212
|
+
"<%= helper.visibility %>",
|
|
213
|
+
<%= helper.tag_name ? "\"#{helper.tag_name}\"" : "null" %>,
|
|
214
|
+
<%= helper.void? %>,
|
|
215
|
+
<%= helper.supports_block %>,
|
|
216
|
+
<%= helper.preferred_for_tag %>,
|
|
217
|
+
<%= helper.supported %>,
|
|
218
|
+
"<%= helper.detect_style || "call_name" %>",
|
|
219
|
+
"<%= helper.escaped_description %>",
|
|
220
|
+
"<%= helper.escaped_signature %>",
|
|
221
|
+
"<%= helper.documentation_url %>",
|
|
222
|
+
<%- if helper.implicit_attribute? -%>
|
|
223
|
+
new HelperImplicitAttribute("<%= helper.implicit_attribute.name %>", "<%= helper.implicit_attribute.source %>", <%= helper.implicit_attribute.source_with_block ? "\"#{helper.implicit_attribute.source_with_block}\"" : "null" %>, "<%= helper.implicit_attribute.wrapper %>"),
|
|
224
|
+
<%- else -%>
|
|
225
|
+
null,
|
|
226
|
+
<%- end -%>
|
|
227
|
+
List.of(<%= helper.arguments.map { |arg| "new HelperArgument(\"#{arg.name}\", #{arg.position}, \"#{arg.type_display}\", #{arg.optional}, #{arg.default ? "\"#{arg.escaped_default}\"" : "null"}, #{arg.splat}, \"#{arg.escaped_description}\")" }.join(", ") %>),
|
|
228
|
+
List.of(<%= helper.options.map { |opt| "new HelperOption(\"#{opt.name}\", \"#{opt.type_display}\", #{opt.maps_to ? "\"#{opt.maps_to}\"" : "null"}, \"#{opt.escaped_description}\")" }.join(", ") %>),
|
|
229
|
+
List.of(<%= helper.special_behaviors.map { |b| "\"#{b}\"" }.join(", ") %>),
|
|
230
|
+
List.of(<%= helper.aliases.map { |a| "\"#{a}\"" }.join(", ") %>)
|
|
231
|
+
);
|
|
232
|
+
byName.put("<%= helper.name %>", entry);
|
|
233
|
+
bySource.put("<%= helper.source %>", entry);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
<%- end -%>
|
|
237
|
+
BY_NAME = Collections.unmodifiableMap(byName);
|
|
238
|
+
BY_SOURCE = Collections.unmodifiableMap(bySource);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
private HelperRegistry() {}
|
|
242
|
+
|
|
243
|
+
public static HelperEntry get(String name) {
|
|
244
|
+
return BY_NAME.get(name);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
public static HelperEntry findBySource(String source) {
|
|
248
|
+
return BY_SOURCE.get(source);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
public static List<HelperEntry> entries() {
|
|
252
|
+
return List.copyOf(BY_NAME.values());
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
public static int count() {
|
|
256
|
+
return BY_NAME.size();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
export enum HelperType {
|
|
2
|
+
<%- helpers.each do |helper| -%>
|
|
3
|
+
<%= helper.camel_case_name %> = "<%= helper.name %>",
|
|
4
|
+
<%- end -%>
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type HelperDetectStyle = "call_name" | "receiver_call"
|
|
8
|
+
export type HelperOutput = "html" | "text" | "url" | "boolean" | "void" | "object"
|
|
9
|
+
|
|
10
|
+
export interface HelperArgument {
|
|
11
|
+
readonly name: string
|
|
12
|
+
readonly position: number
|
|
13
|
+
readonly type: string
|
|
14
|
+
readonly optional: boolean
|
|
15
|
+
readonly default: string | null
|
|
16
|
+
readonly splat: boolean
|
|
17
|
+
readonly description: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface HelperOption {
|
|
21
|
+
readonly name: string
|
|
22
|
+
readonly type: string
|
|
23
|
+
readonly mapsTo: string | null
|
|
24
|
+
readonly description: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface HelperImplicitAttribute {
|
|
28
|
+
readonly name: string
|
|
29
|
+
readonly source: string
|
|
30
|
+
readonly sourceWithBlock: string | null
|
|
31
|
+
readonly wrapper: string
|
|
32
|
+
readonly skipWrappingFor: string[]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface HelperEntry {
|
|
36
|
+
readonly name: string
|
|
37
|
+
readonly type: HelperType
|
|
38
|
+
readonly source: string
|
|
39
|
+
readonly gem: string
|
|
40
|
+
readonly output: HelperOutput
|
|
41
|
+
readonly visibility: "public" | "internal"
|
|
42
|
+
readonly tagName: string | null
|
|
43
|
+
readonly isVoid: boolean
|
|
44
|
+
readonly supportsBlock: boolean
|
|
45
|
+
readonly preferredForTag: boolean
|
|
46
|
+
readonly supported: boolean
|
|
47
|
+
readonly detectStyle: HelperDetectStyle
|
|
48
|
+
readonly description: string
|
|
49
|
+
readonly signature: string
|
|
50
|
+
readonly documentationURL: string
|
|
51
|
+
readonly implicitAttribute: HelperImplicitAttribute | null
|
|
52
|
+
readonly arguments: HelperArgument[]
|
|
53
|
+
readonly options: HelperOption[]
|
|
54
|
+
readonly specialBehaviors: string[]
|
|
55
|
+
readonly aliases: string[]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
<%- helpers.each do |helper| -%>
|
|
59
|
+
const <%= helper.lower_camel_case_name %>Entry: HelperEntry = {
|
|
60
|
+
name: "<%= helper.name %>",
|
|
61
|
+
type: HelperType.<%= helper.camel_case_name %>,
|
|
62
|
+
source: "<%= helper.source %>",
|
|
63
|
+
gem: "<%= helper.gem %>",
|
|
64
|
+
output: "<%= helper.output %>",
|
|
65
|
+
visibility: "<%= helper.visibility %>",
|
|
66
|
+
tagName: <%= helper.tag_name ? "\"#{helper.tag_name}\"" : "null" %>,
|
|
67
|
+
isVoid: <%= helper.void? %>,
|
|
68
|
+
supportsBlock: <%= helper.supports_block %>,
|
|
69
|
+
preferredForTag: <%= helper.preferred_for_tag %>,
|
|
70
|
+
supported: <%= helper.supported %>,
|
|
71
|
+
detectStyle: "<%= helper.detect_style || "call_name" %>",
|
|
72
|
+
description: "<%= helper.escaped_description %>",
|
|
73
|
+
signature: "<%= helper.escaped_signature %>",
|
|
74
|
+
documentationURL: "<%= helper.documentation_url %>",
|
|
75
|
+
<%- if helper.implicit_attribute? -%>
|
|
76
|
+
implicitAttribute: {
|
|
77
|
+
name: "<%= helper.implicit_attribute.name %>",
|
|
78
|
+
source: "<%= helper.implicit_attribute.source %>",
|
|
79
|
+
sourceWithBlock: <%= helper.implicit_attribute.source_with_block ? "\"#{helper.implicit_attribute.source_with_block}\"" : "null" %>,
|
|
80
|
+
wrapper: "<%= helper.implicit_attribute.wrapper %>",
|
|
81
|
+
skipWrappingFor: [<%= helper.implicit_attribute.skip_wrapping_for.map { |s| "\"#{s}\"" }.join(", ") %>],
|
|
82
|
+
},
|
|
83
|
+
<%- else -%>
|
|
84
|
+
implicitAttribute: null,
|
|
85
|
+
<%- end -%>
|
|
86
|
+
arguments: [
|
|
87
|
+
<%- helper.arguments.each do |arg| -%>
|
|
88
|
+
{ name: "<%= arg.name %>", position: <%= arg.position %>, type: "<%= arg.type_display %>", optional: <%= arg.optional %>, default: <%= arg.default ? "\"#{arg.escaped_default}\"" : "null" %>, splat: <%= arg.splat %>, description: "<%= arg.escaped_description %>" },
|
|
89
|
+
<%- end -%>
|
|
90
|
+
],
|
|
91
|
+
options: [
|
|
92
|
+
<%- helper.options.each do |opt| -%>
|
|
93
|
+
{ name: "<%= opt.name %>", type: "<%= opt.type_display %>", mapsTo: <%= opt.maps_to ? "\"#{opt.maps_to}\"" : "null" %>, description: "<%= opt.escaped_description %>" },
|
|
94
|
+
<%- end -%>
|
|
95
|
+
],
|
|
96
|
+
specialBehaviors: [<%= helper.special_behaviors.map { |b| "\"#{b}\"" }.join(", ") %>],
|
|
97
|
+
aliases: [<%= helper.aliases.map { |a| "\"#{a}\"" }.join(", ") %>],
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
<%- end -%>
|
|
101
|
+
export const HELPER_REGISTRY: Record<string, HelperEntry> = {
|
|
102
|
+
<%- helpers.each do |helper| -%>
|
|
103
|
+
"<%= helper.name %>": <%= helper.lower_camel_case_name %>Entry,
|
|
104
|
+
<%- helper.aliases.each do |alias_name| -%>
|
|
105
|
+
"<%= alias_name %>": <%= helper.lower_camel_case_name %>Entry,
|
|
106
|
+
<%- end -%>
|
|
107
|
+
<%- end -%>
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export const HELPER_BY_SOURCE: Record<string, HelperEntry> = {
|
|
111
|
+
<%- helpers.each do |helper| -%>
|
|
112
|
+
"<%= helper.source %>": <%= helper.lower_camel_case_name %>Entry,
|
|
113
|
+
<%- end -%>
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
<%- helpers_by_tag = helpers.select(&:static_tag_name?).group_by(&:tag_name) -%>
|
|
117
|
+
export const HELPERS_BY_TAG_NAME: Record<string, HelperEntry[]> = {
|
|
118
|
+
<%- helpers_by_tag.each do |tag_name, helpers| -%>
|
|
119
|
+
"<%= tag_name %>": [<%= helpers.map { |h| "#{h.lower_camel_case_name}Entry" }.join(", ") %>],
|
|
120
|
+
<%- end -%>
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function getHelper(name: string): HelperEntry | undefined {
|
|
124
|
+
return HELPER_REGISTRY[name]
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function getHelperBySource(source: string): HelperEntry | undefined {
|
|
128
|
+
return HELPER_BY_SOURCE[source]
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function getHelperEntries(): HelperEntry[] {
|
|
132
|
+
return Object.values(HELPER_REGISTRY)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function isHelperSupported(name: string): boolean {
|
|
136
|
+
return HELPER_REGISTRY[name]?.supported ?? false
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function helperExists(name: string): boolean {
|
|
140
|
+
return name in HELPER_REGISTRY
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function getHelpersForTag(tagName: string): HelperEntry[] {
|
|
144
|
+
return HELPERS_BY_TAG_NAME[tagName] ?? []
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function findPreferredHelperForTag(tagName: string): HelperEntry | undefined {
|
|
148
|
+
const helpers = HELPERS_BY_TAG_NAME[tagName]
|
|
149
|
+
if (!helpers) return undefined
|
|
150
|
+
|
|
151
|
+
return helpers.find(entry => entry.preferredForTag) ?? helpers[0]
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function getSupportedHelpers(): HelperEntry[] {
|
|
155
|
+
return Object.values(HELPER_REGISTRY).filter(entry => entry.supported)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function getHelpersByGem(gem: string): HelperEntry[] {
|
|
159
|
+
return Object.values(HELPER_REGISTRY).filter(entry => entry.gem === gem)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function getHelpersByOutput(output: HelperOutput): HelperEntry[] {
|
|
163
|
+
return Object.values(HELPER_REGISTRY).filter(entry => entry.output === output)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function getHelpersByModule(moduleName: string): HelperEntry[] {
|
|
167
|
+
return Object.values(HELPER_REGISTRY).filter(entry => {
|
|
168
|
+
const parts = entry.source.split("#")[0].split("::")
|
|
169
|
+
return parts[parts.length - 1] === moduleName
|
|
170
|
+
})
|
|
171
|
+
}
|
|
@@ -318,7 +318,11 @@ export class <%= node.name %> extends Node {
|
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
accept(visitor: Visitor): void {
|
|
321
|
-
visitor.visit<%= node.name %>(
|
|
321
|
+
const visitMethod = visitor.visit<%= node.name %> as ((node: <%= node.name %>) => void) | undefined
|
|
322
|
+
|
|
323
|
+
if (typeof visitMethod === "function") {
|
|
324
|
+
visitMethod.call(visitor, this)
|
|
325
|
+
}
|
|
322
326
|
}
|
|
323
327
|
|
|
324
328
|
childNodes(): (Node | null | undefined)[] {
|