@herb-tools/node 0.8.10 → 0.9.1

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 (171) hide show
  1. package/binding.gyp +27 -8
  2. package/dist/herb-node.cjs +41 -12
  3. package/dist/herb-node.cjs.map +1 -1
  4. package/dist/herb-node.esm.js +8 -1
  5. package/dist/herb-node.esm.js.map +1 -1
  6. package/dist/types/node-backend.d.ts +3 -1
  7. package/extension/error_helpers.cpp +598 -73
  8. package/extension/error_helpers.h +20 -3
  9. package/extension/extension_helpers.cpp +40 -35
  10. package/extension/extension_helpers.h +2 -2
  11. package/extension/herb.cpp +194 -64
  12. package/extension/libherb/analyze/action_view/attribute_extraction_helpers.c +303 -0
  13. package/extension/libherb/analyze/action_view/attribute_extraction_helpers.h +36 -0
  14. package/extension/libherb/analyze/action_view/content_tag.c +78 -0
  15. package/extension/libherb/analyze/action_view/link_to.c +167 -0
  16. package/extension/libherb/analyze/action_view/registry.c +83 -0
  17. package/extension/libherb/analyze/action_view/tag.c +70 -0
  18. package/extension/libherb/analyze/action_view/tag_helper_handler.h +43 -0
  19. package/extension/libherb/analyze/action_view/tag_helper_node_builders.c +305 -0
  20. package/extension/libherb/analyze/action_view/tag_helper_node_builders.h +70 -0
  21. package/extension/libherb/analyze/action_view/tag_helpers.c +815 -0
  22. package/extension/libherb/analyze/action_view/tag_helpers.h +38 -0
  23. package/extension/libherb/analyze/action_view/turbo_frame_tag.c +88 -0
  24. package/extension/libherb/analyze/analyze.c +885 -0
  25. package/extension/libherb/{include → analyze}/analyze.h +14 -4
  26. package/extension/libherb/{analyzed_ruby.c → analyze/analyzed_ruby.c} +13 -11
  27. package/extension/libherb/{analyzed_ruby.h → analyze/analyzed_ruby.h} +3 -3
  28. package/extension/libherb/analyze/builders.c +343 -0
  29. package/extension/libherb/analyze/builders.h +27 -0
  30. package/extension/libherb/analyze/conditional_elements.c +594 -0
  31. package/extension/libherb/analyze/conditional_elements.h +9 -0
  32. package/extension/libherb/analyze/conditional_open_tags.c +640 -0
  33. package/extension/libherb/analyze/conditional_open_tags.h +9 -0
  34. package/extension/libherb/analyze/control_type.c +250 -0
  35. package/extension/libherb/analyze/control_type.h +14 -0
  36. package/extension/libherb/{analyze_helpers.c → analyze/helpers.c} +48 -23
  37. package/extension/libherb/{analyze_helpers.h → analyze/helpers.h} +4 -2
  38. package/extension/libherb/analyze/invalid_structures.c +193 -0
  39. package/extension/libherb/analyze/invalid_structures.h +11 -0
  40. package/extension/libherb/{analyze_missing_end.c → analyze/missing_end.c} +33 -22
  41. package/extension/libherb/analyze/parse_errors.c +84 -0
  42. package/extension/libherb/analyze/prism_annotate.c +399 -0
  43. package/extension/libherb/analyze/prism_annotate.h +16 -0
  44. package/extension/libherb/analyze/render_nodes.c +761 -0
  45. package/extension/libherb/analyze/render_nodes.h +11 -0
  46. package/extension/libherb/{analyze_transform.c → analyze/transform.c} +24 -3
  47. package/extension/libherb/ast_node.c +17 -7
  48. package/extension/libherb/ast_node.h +11 -5
  49. package/extension/libherb/ast_nodes.c +760 -388
  50. package/extension/libherb/ast_nodes.h +155 -39
  51. package/extension/libherb/ast_pretty_print.c +265 -7
  52. package/extension/libherb/ast_pretty_print.h +6 -1
  53. package/extension/libherb/element_source.h +3 -8
  54. package/extension/libherb/errors.c +1455 -520
  55. package/extension/libherb/errors.h +207 -56
  56. package/extension/libherb/extract.c +145 -49
  57. package/extension/libherb/extract.h +21 -5
  58. package/extension/libherb/herb.c +52 -34
  59. package/extension/libherb/herb.h +18 -6
  60. package/extension/libherb/herb_prism_node.h +13 -0
  61. package/extension/libherb/html_util.c +241 -12
  62. package/extension/libherb/html_util.h +7 -2
  63. package/extension/libherb/include/analyze/action_view/attribute_extraction_helpers.h +36 -0
  64. package/extension/libherb/include/analyze/action_view/tag_helper_handler.h +43 -0
  65. package/extension/libherb/include/analyze/action_view/tag_helper_node_builders.h +70 -0
  66. package/extension/libherb/include/analyze/action_view/tag_helpers.h +38 -0
  67. package/extension/libherb/{analyze.h → include/analyze/analyze.h} +14 -4
  68. package/extension/libherb/include/{analyzed_ruby.h → analyze/analyzed_ruby.h} +3 -3
  69. package/extension/libherb/include/analyze/builders.h +27 -0
  70. package/extension/libherb/include/analyze/conditional_elements.h +9 -0
  71. package/extension/libherb/include/analyze/conditional_open_tags.h +9 -0
  72. package/extension/libherb/include/analyze/control_type.h +14 -0
  73. package/extension/libherb/include/{analyze_helpers.h → analyze/helpers.h} +4 -2
  74. package/extension/libherb/include/analyze/invalid_structures.h +11 -0
  75. package/extension/libherb/include/analyze/prism_annotate.h +16 -0
  76. package/extension/libherb/include/analyze/render_nodes.h +11 -0
  77. package/extension/libherb/include/ast_node.h +11 -5
  78. package/extension/libherb/include/ast_nodes.h +155 -39
  79. package/extension/libherb/include/ast_pretty_print.h +6 -1
  80. package/extension/libherb/include/element_source.h +3 -8
  81. package/extension/libherb/include/errors.h +207 -56
  82. package/extension/libherb/include/extract.h +21 -5
  83. package/extension/libherb/include/herb.h +18 -6
  84. package/extension/libherb/include/herb_prism_node.h +13 -0
  85. package/extension/libherb/include/html_util.h +7 -2
  86. package/extension/libherb/include/io.h +3 -1
  87. package/extension/libherb/include/lex_helpers.h +29 -0
  88. package/extension/libherb/include/lexer.h +1 -1
  89. package/extension/libherb/include/lexer_peek_helpers.h +87 -13
  90. package/extension/libherb/include/lexer_struct.h +2 -0
  91. package/extension/libherb/include/location.h +2 -1
  92. package/extension/libherb/include/parser.h +28 -2
  93. package/extension/libherb/include/parser_helpers.h +19 -3
  94. package/extension/libherb/include/pretty_print.h +10 -5
  95. package/extension/libherb/include/prism_context.h +45 -0
  96. package/extension/libherb/include/prism_helpers.h +10 -7
  97. package/extension/libherb/include/prism_serialized.h +12 -0
  98. package/extension/libherb/include/token.h +16 -4
  99. package/extension/libherb/include/token_struct.h +10 -3
  100. package/extension/libherb/include/utf8.h +2 -1
  101. package/extension/libherb/include/util/hb_allocator.h +78 -0
  102. package/extension/libherb/include/util/hb_arena.h +6 -1
  103. package/extension/libherb/include/util/hb_arena_debug.h +12 -1
  104. package/extension/libherb/include/util/hb_array.h +7 -3
  105. package/extension/libherb/include/util/hb_buffer.h +6 -4
  106. package/extension/libherb/include/util/hb_foreach.h +79 -0
  107. package/extension/libherb/include/util/hb_narray.h +8 -4
  108. package/extension/libherb/include/util/hb_string.h +56 -9
  109. package/extension/libherb/include/util.h +6 -3
  110. package/extension/libherb/include/version.h +1 -1
  111. package/extension/libherb/io.c +3 -2
  112. package/extension/libherb/io.h +3 -1
  113. package/extension/libherb/lex_helpers.h +29 -0
  114. package/extension/libherb/lexer.c +42 -30
  115. package/extension/libherb/lexer.h +1 -1
  116. package/extension/libherb/lexer_peek_helpers.c +12 -74
  117. package/extension/libherb/lexer_peek_helpers.h +87 -13
  118. package/extension/libherb/lexer_struct.h +2 -0
  119. package/extension/libherb/location.c +2 -2
  120. package/extension/libherb/location.h +2 -1
  121. package/extension/libherb/main.c +53 -28
  122. package/extension/libherb/parser.c +784 -247
  123. package/extension/libherb/parser.h +28 -2
  124. package/extension/libherb/parser_helpers.c +110 -23
  125. package/extension/libherb/parser_helpers.h +19 -3
  126. package/extension/libherb/parser_match_tags.c +130 -49
  127. package/extension/libherb/pretty_print.c +29 -24
  128. package/extension/libherb/pretty_print.h +10 -5
  129. package/extension/libherb/prism_context.h +45 -0
  130. package/extension/libherb/prism_helpers.c +30 -27
  131. package/extension/libherb/prism_helpers.h +10 -7
  132. package/extension/libherb/prism_serialized.h +12 -0
  133. package/extension/libherb/ruby_parser.c +2 -0
  134. package/extension/libherb/token.c +151 -66
  135. package/extension/libherb/token.h +16 -4
  136. package/extension/libherb/token_matchers.c +0 -1
  137. package/extension/libherb/token_struct.h +10 -3
  138. package/extension/libherb/utf8.c +7 -6
  139. package/extension/libherb/utf8.h +2 -1
  140. package/extension/libherb/util/hb_allocator.c +341 -0
  141. package/extension/libherb/util/hb_allocator.h +78 -0
  142. package/extension/libherb/util/hb_arena.c +81 -56
  143. package/extension/libherb/util/hb_arena.h +6 -1
  144. package/extension/libherb/util/hb_arena_debug.c +32 -17
  145. package/extension/libherb/util/hb_arena_debug.h +12 -1
  146. package/extension/libherb/util/hb_array.c +30 -15
  147. package/extension/libherb/util/hb_array.h +7 -3
  148. package/extension/libherb/util/hb_buffer.c +17 -21
  149. package/extension/libherb/util/hb_buffer.h +6 -4
  150. package/extension/libherb/util/hb_foreach.h +79 -0
  151. package/extension/libherb/util/hb_narray.c +22 -7
  152. package/extension/libherb/util/hb_narray.h +8 -4
  153. package/extension/libherb/util/hb_string.c +49 -35
  154. package/extension/libherb/util/hb_string.h +56 -9
  155. package/extension/libherb/util.c +21 -11
  156. package/extension/libherb/util.h +6 -3
  157. package/extension/libherb/version.h +1 -1
  158. package/extension/libherb/visitor.c +68 -1
  159. package/extension/nodes.cpp +593 -6
  160. package/extension/nodes.h +10 -1
  161. package/package.json +12 -8
  162. package/src/node-backend.ts +11 -1
  163. package/dist/types/index-cjs.d.cts +0 -1
  164. package/extension/libherb/analyze.c +0 -1608
  165. package/extension/libherb/element_source.c +0 -12
  166. package/extension/libherb/include/util/hb_system.h +0 -9
  167. package/extension/libherb/util/hb_system.c +0 -30
  168. package/extension/libherb/util/hb_system.h +0 -9
  169. package/src/index-cjs.cts +0 -22
  170. /package/dist/types/{index-esm.d.mts → index.d.ts} +0 -0
  171. /package/src/{index-esm.mts → index.ts} +0 -0
@@ -0,0 +1,70 @@
1
+ #include "../../include/analyze/action_view/tag_helper_handler.h"
2
+
3
+ #include <prism.h>
4
+ #include <stdbool.h>
5
+ #include <stdlib.h>
6
+ #include <string.h>
7
+
8
+ bool detect_tag_dot(pm_call_node_t* call_node, pm_parser_t* parser) {
9
+ if (!call_node || !call_node->receiver) { return false; }
10
+ if (call_node->receiver->type != PM_CALL_NODE) { return false; }
11
+
12
+ pm_call_node_t* receiver_node = (pm_call_node_t*) call_node->receiver;
13
+ if (!receiver_node->name) { return false; }
14
+
15
+ pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, receiver_node->name);
16
+
17
+ return constant && constant->length == 3 && strncmp((const char*) constant->start, "tag", 3) == 0;
18
+ }
19
+
20
+ char* extract_tag_dot_name(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator) {
21
+ if (!call_node || !call_node->name) { return NULL; }
22
+
23
+ pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, call_node->name);
24
+ if (!constant) { return NULL; }
25
+
26
+ char* name = hb_allocator_strndup(allocator, (const char*) constant->start, constant->length);
27
+
28
+ for (size_t i = 0; i < constant->length && name[i] != '\0'; i++) {
29
+ if (name[i] == '_') { name[i] = '-'; }
30
+ }
31
+
32
+ return name;
33
+ }
34
+
35
+ // TODO: this should probably be an array of nodes
36
+ char* extract_tag_dot_content(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator) {
37
+ (void) parser;
38
+
39
+ if (!call_node) { return NULL; }
40
+
41
+ char* block_content = extract_inline_block_content(call_node, allocator);
42
+ if (block_content) { return block_content; }
43
+
44
+ if (call_node->arguments) {
45
+ pm_arguments_node_t* arguments = call_node->arguments;
46
+
47
+ if (arguments->arguments.size) {
48
+ pm_node_t* first_argument = arguments->arguments.nodes[0];
49
+
50
+ if (first_argument->type == PM_STRING_NODE) {
51
+ pm_string_node_t* string_node = (pm_string_node_t*) first_argument;
52
+ size_t length = pm_string_length(&string_node->unescaped);
53
+ return hb_allocator_strndup(allocator, (const char*) pm_string_source(&string_node->unescaped), length);
54
+ }
55
+ }
56
+ }
57
+
58
+ return NULL;
59
+ }
60
+
61
+ bool tag_dot_supports_block(void) {
62
+ return true;
63
+ }
64
+
65
+ const tag_helper_handler_T tag_dot_handler = { .name = "tag",
66
+ .source = HB_STRING_LITERAL("ActionView::Helpers::TagHelper#tag"),
67
+ .detect = detect_tag_dot,
68
+ .extract_tag_name = extract_tag_dot_name,
69
+ .extract_content = extract_tag_dot_content,
70
+ .supports_block = tag_dot_supports_block };
@@ -0,0 +1,43 @@
1
+ #ifndef TAG_HELPER_HANDLER_H
2
+ #define TAG_HELPER_HANDLER_H
3
+
4
+ #include "../../util/hb_allocator.h"
5
+ #include "../../util/hb_array.h"
6
+ #include "../../util/hb_string.h"
7
+ #include <prism.h>
8
+ #include <stdbool.h>
9
+
10
+ typedef struct {
11
+ char* tag_name;
12
+ pm_call_node_t* call_node;
13
+ hb_array_T* attributes;
14
+ char* content;
15
+ bool content_is_ruby_expression;
16
+ bool has_block;
17
+ hb_allocator_T* allocator;
18
+ } tag_helper_info_T;
19
+
20
+ typedef struct {
21
+ const char* name;
22
+ hb_string_T source;
23
+ bool (*detect)(pm_call_node_t* call_node, pm_parser_t* parser);
24
+ char* (*extract_tag_name)(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator);
25
+ char* (*extract_content)(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator);
26
+ hb_array_T* (*extract_attributes)(
27
+ pm_call_node_t* call_node,
28
+ const uint8_t* source,
29
+ const char* original_source,
30
+ size_t erb_content_offset
31
+ );
32
+ bool (*supports_block)(void);
33
+ } tag_helper_handler_T;
34
+
35
+ tag_helper_info_T* tag_helper_info_init(hb_allocator_T* allocator);
36
+ void tag_helper_info_free(tag_helper_info_T** info);
37
+
38
+ tag_helper_handler_T* get_tag_helper_handlers(void);
39
+ size_t get_tag_helper_handlers_count(void);
40
+
41
+ char* extract_inline_block_content(pm_call_node_t* call_node, hb_allocator_T* allocator);
42
+
43
+ #endif
@@ -0,0 +1,305 @@
1
+ #include "../../include/analyze/action_view/tag_helper_node_builders.h"
2
+ #include "../../include/ast_nodes.h"
3
+ #include "../../include/location.h"
4
+ #include "../../include/position.h"
5
+ #include "../../include/range.h"
6
+ #include "../../include/token_struct.h"
7
+ #include "../../include/util/hb_allocator.h"
8
+ #include "../../include/util/hb_array.h"
9
+ #include "../../include/util/hb_string.h"
10
+
11
+ #include <prism.h>
12
+ #include <stdbool.h>
13
+ #include <stdlib.h>
14
+ #include <string.h>
15
+
16
+ token_T* create_synthetic_token(
17
+ hb_allocator_T* allocator,
18
+ const char* value,
19
+ token_type_T type,
20
+ position_T start,
21
+ position_T end
22
+ ) {
23
+ token_T* token = hb_allocator_alloc(allocator, sizeof(token_T));
24
+ if (!token) { return NULL; }
25
+
26
+ if (value) {
27
+ size_t length = strlen(value);
28
+ char* copied = hb_allocator_strndup(allocator, value, length);
29
+ token->value = (hb_string_T) { .data = copied, .length = (uint32_t) length };
30
+ } else {
31
+ token->value = HB_STRING_EMPTY;
32
+ }
33
+
34
+ token->type = type;
35
+ location_from_positions(&token->location, start, end);
36
+ token->range = (range_T) { .from = 0, .to = 0 };
37
+
38
+ return token;
39
+ }
40
+
41
+ AST_HTML_ATTRIBUTE_NAME_NODE_T* create_attribute_name_node(
42
+ const char* name_string,
43
+ position_T start_position,
44
+ position_T end_position,
45
+ hb_allocator_T* allocator
46
+ ) {
47
+ AST_LITERAL_NODE_T* name_literal = ast_literal_node_init(
48
+ hb_string_from_c_string(name_string),
49
+ start_position,
50
+ end_position,
51
+ hb_array_init(0, allocator),
52
+ allocator
53
+ );
54
+
55
+ hb_array_T* name_children = hb_array_init(1, allocator);
56
+ hb_array_append(name_children, (AST_NODE_T*) name_literal);
57
+
58
+ return ast_html_attribute_name_node_init(
59
+ name_children,
60
+ start_position,
61
+ end_position,
62
+ hb_array_init(0, allocator),
63
+ allocator
64
+ );
65
+ }
66
+
67
+ hb_array_T* prepend_attribute(hb_array_T* attributes, AST_NODE_T* attribute, hb_allocator_T* allocator) {
68
+ hb_array_T* new_attributes = hb_array_init(hb_array_size(attributes) + 1, allocator);
69
+ hb_array_append(new_attributes, attribute);
70
+
71
+ for (size_t i = 0; i < hb_array_size(attributes); i++) {
72
+ hb_array_append(new_attributes, hb_array_get(attributes, i));
73
+ }
74
+
75
+ hb_array_free(&attributes);
76
+ return new_attributes;
77
+ }
78
+
79
+ AST_HTML_ATTRIBUTE_NODE_T* create_html_attribute_node(
80
+ const char* name_string,
81
+ const char* value_string,
82
+ position_T start_position,
83
+ position_T end_position,
84
+ hb_allocator_T* allocator
85
+ ) {
86
+ if (!name_string) { return NULL; }
87
+
88
+ AST_HTML_ATTRIBUTE_NAME_NODE_T* name_node =
89
+ create_attribute_name_node(name_string, start_position, end_position, allocator);
90
+
91
+ token_T* equals_token = create_synthetic_token(allocator, "=", TOKEN_EQUALS, start_position, end_position);
92
+ AST_HTML_ATTRIBUTE_VALUE_NODE_T* value_node = NULL;
93
+
94
+ if (value_string) {
95
+ token_T* open_quote = create_synthetic_token(allocator, "\"", TOKEN_QUOTE, start_position, end_position);
96
+ token_T* close_quote = create_synthetic_token(allocator, "\"", TOKEN_QUOTE, end_position, end_position);
97
+
98
+ AST_LITERAL_NODE_T* value_literal = ast_literal_node_init(
99
+ hb_string_from_c_string(value_string),
100
+ start_position,
101
+ end_position,
102
+ hb_array_init(0, allocator),
103
+ allocator
104
+ );
105
+ hb_array_T* value_children = hb_array_init(1, allocator);
106
+ hb_array_append(value_children, (AST_NODE_T*) value_literal);
107
+
108
+ value_node = ast_html_attribute_value_node_init(
109
+ open_quote,
110
+ value_children,
111
+ close_quote,
112
+ true,
113
+ start_position,
114
+ end_position,
115
+ hb_array_init(0, allocator),
116
+ allocator
117
+ );
118
+ }
119
+
120
+ return ast_html_attribute_node_init(
121
+ name_node,
122
+ equals_token,
123
+ value_node,
124
+ start_position,
125
+ end_position,
126
+ hb_array_init(0, allocator),
127
+ allocator
128
+ );
129
+ }
130
+
131
+ AST_HTML_ATTRIBUTE_NODE_T* create_html_attribute_with_ruby_literal(
132
+ const char* name_string,
133
+ const char* ruby_content,
134
+ position_T start_position,
135
+ position_T end_position,
136
+ hb_allocator_T* allocator
137
+ ) {
138
+ if (!name_string || !ruby_content) { return NULL; }
139
+
140
+ AST_HTML_ATTRIBUTE_NAME_NODE_T* name_node =
141
+ create_attribute_name_node(name_string, start_position, end_position, allocator);
142
+
143
+ token_T* equals_token = create_synthetic_token(allocator, ":", TOKEN_COLON, start_position, end_position);
144
+
145
+ AST_RUBY_LITERAL_NODE_T* ruby_node = ast_ruby_literal_node_init(
146
+ hb_string_from_c_string(ruby_content),
147
+ start_position,
148
+ end_position,
149
+ hb_array_init(0, allocator),
150
+ allocator
151
+ );
152
+
153
+ hb_array_T* value_children = hb_array_init(1, allocator);
154
+ hb_array_append(value_children, (AST_NODE_T*) ruby_node);
155
+
156
+ AST_HTML_ATTRIBUTE_VALUE_NODE_T* value_node = ast_html_attribute_value_node_init(
157
+ NULL,
158
+ value_children,
159
+ NULL,
160
+ false,
161
+ start_position,
162
+ end_position,
163
+ hb_array_init(0, allocator),
164
+ allocator
165
+ );
166
+
167
+ return ast_html_attribute_node_init(
168
+ name_node,
169
+ equals_token,
170
+ value_node,
171
+ start_position,
172
+ end_position,
173
+ hb_array_init(0, allocator),
174
+ allocator
175
+ );
176
+ }
177
+
178
+ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* create_interpolated_attribute_value(
179
+ pm_interpolated_string_node_t* interpolated_node,
180
+ position_T start_position,
181
+ position_T end_position,
182
+ hb_allocator_T* allocator
183
+ ) {
184
+ if (!interpolated_node) { return NULL; }
185
+
186
+ hb_array_T* value_children = hb_array_init(8, allocator);
187
+
188
+ for (size_t i = 0; i < interpolated_node->parts.size; i++) {
189
+ pm_node_t* part = interpolated_node->parts.nodes[i];
190
+
191
+ if (part->type == PM_STRING_NODE) {
192
+ pm_string_node_t* string_part = (pm_string_node_t*) part;
193
+ size_t content_length = pm_string_length(&string_part->unescaped);
194
+
195
+ if (content_length > 0) {
196
+ char* content =
197
+ hb_allocator_strndup(allocator, (const char*) pm_string_source(&string_part->unescaped), content_length);
198
+ if (content) {
199
+ AST_LITERAL_NODE_T* literal_node = ast_literal_node_init(
200
+ hb_string_from_c_string(content),
201
+ start_position,
202
+ end_position,
203
+ hb_array_init(0, allocator),
204
+ allocator
205
+ );
206
+
207
+ if (literal_node) { hb_array_append(value_children, (AST_NODE_T*) literal_node); }
208
+
209
+ hb_allocator_dealloc(allocator, content);
210
+ }
211
+ }
212
+ } else if (part->type == PM_EMBEDDED_STATEMENTS_NODE) {
213
+ size_t ruby_length = part->location.end - part->location.start;
214
+ char* ruby_content = hb_allocator_strndup(allocator, (const char*) part->location.start, ruby_length);
215
+
216
+ if (ruby_content) {
217
+ AST_RUBY_LITERAL_NODE_T* ruby_node = ast_ruby_literal_node_init(
218
+ hb_string_from_c_string(ruby_content),
219
+ start_position,
220
+ end_position,
221
+ hb_array_init(0, allocator),
222
+ allocator
223
+ );
224
+
225
+ if (ruby_node) { hb_array_append(value_children, (AST_NODE_T*) ruby_node); }
226
+
227
+ hb_allocator_dealloc(allocator, ruby_content);
228
+ }
229
+ }
230
+ }
231
+
232
+ return ast_html_attribute_value_node_init(
233
+ NULL,
234
+ value_children,
235
+ NULL,
236
+ false,
237
+ start_position,
238
+ end_position,
239
+ hb_array_init(0, allocator),
240
+ allocator
241
+ );
242
+ }
243
+
244
+ AST_HTML_ATTRIBUTE_NODE_T* create_html_attribute_with_interpolated_value(
245
+ const char* name_string,
246
+ pm_interpolated_string_node_t* interpolated_node,
247
+ position_T start_position,
248
+ position_T end_position,
249
+ hb_allocator_T* allocator
250
+ ) {
251
+ if (!name_string || !interpolated_node) { return NULL; }
252
+
253
+ AST_HTML_ATTRIBUTE_NAME_NODE_T* name_node =
254
+ create_attribute_name_node(name_string, start_position, end_position, allocator);
255
+
256
+ AST_HTML_ATTRIBUTE_VALUE_NODE_T* value_node =
257
+ create_interpolated_attribute_value(interpolated_node, start_position, end_position, allocator);
258
+
259
+ token_T* equals_token = create_synthetic_token(allocator, "=", TOKEN_EQUALS, start_position, end_position);
260
+
261
+ return ast_html_attribute_node_init(
262
+ name_node,
263
+ equals_token,
264
+ value_node,
265
+ start_position,
266
+ end_position,
267
+ hb_array_init(0, allocator),
268
+ allocator
269
+ );
270
+ }
271
+
272
+ AST_HTML_ATTRIBUTE_NODE_T* create_href_attribute(
273
+ const char* href,
274
+ bool is_ruby_expression,
275
+ position_T start_position,
276
+ position_T end_position,
277
+ hb_allocator_T* allocator
278
+ ) {
279
+ return is_ruby_expression
280
+ ? create_html_attribute_with_ruby_literal("href", href, start_position, end_position, allocator)
281
+ : create_html_attribute_node("href", href, start_position, end_position, allocator);
282
+ }
283
+
284
+ void append_body_content_node(
285
+ hb_array_T* body,
286
+ const char* content,
287
+ bool is_ruby_expression,
288
+ position_T start,
289
+ position_T end,
290
+ hb_allocator_T* allocator
291
+ ) {
292
+ if (!content || !body) { return; }
293
+
294
+ if (is_ruby_expression) {
295
+ AST_RUBY_LITERAL_NODE_T* ruby_node =
296
+ ast_ruby_literal_node_init(hb_string_from_c_string(content), start, end, hb_array_init(0, allocator), allocator);
297
+
298
+ if (ruby_node) { hb_array_append(body, (AST_NODE_T*) ruby_node); }
299
+ } else {
300
+ AST_HTML_TEXT_NODE_T* text_node =
301
+ ast_html_text_node_init(hb_string_from_c_string(content), start, end, hb_array_init(0, allocator), allocator);
302
+
303
+ if (text_node) { hb_array_append(body, (AST_NODE_T*) text_node); }
304
+ }
305
+ }
@@ -0,0 +1,70 @@
1
+ #ifndef HERB_ANALYZE_TAG_HELPER_NODE_BUILDERS_H
2
+ #define HERB_ANALYZE_TAG_HELPER_NODE_BUILDERS_H
3
+
4
+ #include "../../ast_nodes.h"
5
+ #include "../../position.h"
6
+ #include "../../token_struct.h"
7
+ #include "../../util/hb_allocator.h"
8
+ #include "../../util/hb_array.h"
9
+
10
+ #include <prism.h>
11
+
12
+ token_T* create_synthetic_token(
13
+ hb_allocator_T* allocator,
14
+ const char* value,
15
+ token_type_T type,
16
+ position_T start,
17
+ position_T end
18
+ );
19
+
20
+ AST_HTML_ATTRIBUTE_NAME_NODE_T* create_attribute_name_node(
21
+ const char* name_string,
22
+ position_T start_position,
23
+ position_T end_position,
24
+ hb_allocator_T* allocator
25
+ );
26
+
27
+ AST_HTML_ATTRIBUTE_NODE_T* create_html_attribute_node(
28
+ const char* name_string,
29
+ const char* value_string,
30
+ position_T start_position,
31
+ position_T end_position,
32
+ hb_allocator_T* allocator
33
+ );
34
+
35
+ AST_HTML_ATTRIBUTE_NODE_T* create_html_attribute_with_ruby_literal(
36
+ const char* name_string,
37
+ const char* ruby_content,
38
+ position_T start_position,
39
+ position_T end_position,
40
+ hb_allocator_T* allocator
41
+ );
42
+
43
+ AST_HTML_ATTRIBUTE_NODE_T* create_html_attribute_with_interpolated_value(
44
+ const char* name_string,
45
+ pm_interpolated_string_node_t* interpolated_node,
46
+ position_T start_position,
47
+ position_T end_position,
48
+ hb_allocator_T* allocator
49
+ );
50
+
51
+ hb_array_T* prepend_attribute(hb_array_T* attributes, AST_NODE_T* attribute, hb_allocator_T* allocator);
52
+
53
+ AST_HTML_ATTRIBUTE_NODE_T* create_href_attribute(
54
+ const char* href,
55
+ bool is_ruby_expression,
56
+ position_T start_position,
57
+ position_T end_position,
58
+ hb_allocator_T* allocator
59
+ );
60
+
61
+ void append_body_content_node(
62
+ hb_array_T* body,
63
+ const char* content,
64
+ bool is_ruby_expression,
65
+ position_T start,
66
+ position_T end,
67
+ hb_allocator_T* allocator
68
+ );
69
+
70
+ #endif