herb 0.9.7-arm-linux-gnu → 0.10.0-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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/ext/herb/extconf.rb +1 -0
  4. data/ext/herb/extension.c +108 -0
  5. data/herb.gemspec +1 -1
  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/render_analyzer.rb +1057 -0
  11. data/lib/herb/ast/erb_render_node.rb +155 -0
  12. data/lib/herb/bootstrap.rb +0 -1
  13. data/lib/herb/cli.rb +253 -19
  14. data/lib/herb/colors.rb +18 -0
  15. data/lib/herb/configuration.rb +49 -13
  16. data/lib/herb/defaults.yml +3 -0
  17. data/lib/herb/dev/runner.rb +445 -0
  18. data/lib/herb/dev/server.rb +207 -0
  19. data/lib/herb/dev/server_entry.rb +128 -0
  20. data/lib/herb/diff_operation.rb +34 -0
  21. data/lib/herb/diff_result.rb +59 -0
  22. data/lib/herb/engine/compiler.rb +56 -3
  23. data/lib/herb/engine/validators/render_validator.rb +92 -0
  24. data/lib/herb/engine.rb +58 -4
  25. data/lib/herb/html/util.rb +16 -0
  26. data/lib/herb/project.rb +1 -6
  27. data/lib/herb/version.rb +1 -1
  28. data/lib/herb.rb +41 -5
  29. data/sig/herb/action_view/render_analyzer.rbs +122 -0
  30. data/sig/herb/ast/erb_render_node.rbs +29 -0
  31. data/sig/herb/colors.rbs +12 -0
  32. data/sig/herb/configuration.rbs +20 -1
  33. data/sig/herb/dev/runner.rbs +59 -0
  34. data/sig/herb/dev/server.rbs +50 -0
  35. data/sig/herb/dev/server_entry.rbs +51 -0
  36. data/sig/herb/diff_operation.rbs +34 -0
  37. data/sig/herb/diff_result.rbs +34 -0
  38. data/sig/herb/engine/compiler.rbs +6 -0
  39. data/sig/herb/engine/validators/render_validator.rbs +21 -0
  40. data/sig/herb/engine.rbs +15 -0
  41. data/sig/herb/html/util.rbs +13 -0
  42. data/sig/herb.rbs +12 -2
  43. data/sig/herb_c_extension.rbs +1 -1
  44. data/sig/vendor/did_you_mean.rbs +6 -0
  45. data/sig/vendor/parallel.rbs +4 -0
  46. data/src/analyze/action_view/attribute_extraction_helpers.c +3 -2
  47. data/src/diff/herb_diff.c +137 -0
  48. data/src/diff/herb_diff_attributes.c +207 -0
  49. data/src/diff/herb_diff_children.c +518 -0
  50. data/src/diff/herb_diff_helpers.c +114 -0
  51. data/src/diff/herb_diff_nodes.c +707 -0
  52. data/src/diff/herb_hash.c +42 -0
  53. data/src/diff/herb_hash_index_map.c +47 -0
  54. data/src/diff/herb_hash_map.c +104 -0
  55. data/src/diff/herb_hash_tree.c +680 -0
  56. data/src/include/diff/herb_diff.h +118 -0
  57. data/src/include/diff/herb_hash.h +25 -0
  58. data/src/include/diff/herb_hash_index_map.h +32 -0
  59. data/src/include/diff/herb_hash_map.h +30 -0
  60. data/src/include/herb.h +1 -0
  61. data/src/include/version.h +1 -1
  62. data/templates/javascript/packages/core/src/config.ts.erb +43 -0
  63. data/templates/rust/src/ast/nodes.rs.erb +1 -1
  64. data/templates/rust/src/config.rs.erb +50 -0
  65. data/templates/src/diff/herb_diff_helpers.c.erb +38 -0
  66. data/templates/src/diff/herb_diff_nodes.c.erb +224 -0
  67. data/templates/src/diff/herb_hash_tree.c.erb +147 -0
  68. data/templates/template.rb +4 -4
  69. metadata +40 -4
  70. data/lib/herb/3.0/herb.so +0 -0
  71. data/lib/herb/3.1/herb.so +0 -0
@@ -0,0 +1,137 @@
1
+ // Tree diffing algorithm inspired by React's Reconciliation approach:
2
+ // comparing trees level-by-level and producing a minimal set of operations.
3
+ // https://legacy.reactjs.org/docs/reconciliation.html
4
+
5
+ #include "../include/diff/herb_diff.h"
6
+
7
+ #include <stdio.h>
8
+
9
+ herb_diff_path_T herb_diff_path_empty(void) {
10
+ herb_diff_path_T path;
11
+
12
+ path.depth = 0;
13
+
14
+ return path;
15
+ }
16
+
17
+ herb_diff_path_T herb_diff_path_append(const herb_diff_path_T path, const uint32_t index) {
18
+ herb_diff_path_T result = path;
19
+
20
+ if (result.depth < HERB_DIFF_PATH_MAX_DEPTH) {
21
+ result.indices[result.depth] = index;
22
+ result.depth++;
23
+ } else {
24
+ fprintf(stderr, "herb: diff path depth exceeded maximum of %d\n", HERB_DIFF_PATH_MAX_DEPTH);
25
+ }
26
+
27
+ return result;
28
+ }
29
+
30
+ static void emit_operation(
31
+ herb_diff_result_T* result,
32
+ const herb_diff_operation_type_T type,
33
+ const herb_diff_path_T path,
34
+ const AST_NODE_T* old_node,
35
+ const AST_NODE_T* new_node,
36
+ const uint32_t old_index,
37
+ const uint32_t new_index
38
+ ) {
39
+ herb_diff_operation_T* operation =
40
+ (herb_diff_operation_T*) hb_allocator_alloc(result->allocator, sizeof(herb_diff_operation_T));
41
+
42
+ operation->type = type;
43
+ operation->path = path;
44
+ operation->old_node = old_node;
45
+ operation->new_node = new_node;
46
+ operation->old_index = old_index;
47
+ operation->new_index = new_index;
48
+
49
+ hb_array_append(result->operations, operation);
50
+ }
51
+
52
+ herb_diff_result_T* herb_diff(
53
+ const AST_DOCUMENT_NODE_T* old_document,
54
+ const AST_DOCUMENT_NODE_T* new_document,
55
+ hb_allocator_T* allocator
56
+ ) {
57
+ herb_diff_result_T* result = (herb_diff_result_T*) hb_allocator_alloc(allocator, sizeof(herb_diff_result_T));
58
+ result->operations = hb_array_init(16, allocator);
59
+ result->allocator = allocator;
60
+ result->trees_identical = false;
61
+
62
+ herb_hash_map_T old_hashes;
63
+ herb_hash_map_T new_hashes;
64
+
65
+ herb_hash_map_init(&old_hashes, 256, allocator);
66
+ herb_hash_map_init(&new_hashes, 256, allocator);
67
+
68
+ herb_hash_T old_root_hash = herb_hash_tree((const AST_NODE_T*) old_document, &old_hashes);
69
+ herb_hash_T new_root_hash = herb_hash_tree((const AST_NODE_T*) new_document, &new_hashes);
70
+
71
+ if (old_root_hash == new_root_hash) {
72
+ result->trees_identical = true;
73
+ return result;
74
+ }
75
+
76
+ herb_diff_path_T root_path = herb_diff_path_empty();
77
+
78
+ herb_diff_node(
79
+ (const AST_NODE_T*) old_document,
80
+ (const AST_NODE_T*) new_document,
81
+ root_path,
82
+ &old_hashes,
83
+ &new_hashes,
84
+ result
85
+ );
86
+
87
+ return result;
88
+ }
89
+
90
+ size_t herb_diff_operation_count(const herb_diff_result_T* result) {
91
+ if (result == NULL || result->operations == NULL) { return 0; }
92
+
93
+ return hb_array_size(result->operations);
94
+ }
95
+
96
+ const herb_diff_operation_T* herb_diff_operation_at(const herb_diff_result_T* result, const size_t index) {
97
+ if (result == NULL || result->operations == NULL) { return NULL; }
98
+
99
+ return (const herb_diff_operation_T*) hb_array_get(result->operations, index);
100
+ }
101
+
102
+ bool herb_diff_trees_identical(const herb_diff_result_T* result) {
103
+ if (result == NULL) { return false; }
104
+
105
+ return result->trees_identical;
106
+ }
107
+
108
+ const char* herb_diff_operation_type_to_string(const herb_diff_operation_type_T type) {
109
+ switch (type) {
110
+ case HERB_DIFF_ATTRIBUTE_ADDED: return "attribute_added";
111
+ case HERB_DIFF_ATTRIBUTE_REMOVED: return "attribute_removed";
112
+ case HERB_DIFF_ATTRIBUTE_VALUE_CHANGED: return "attribute_value_changed";
113
+ case HERB_DIFF_ERB_CONTENT_CHANGED: return "erb_content_changed";
114
+ case HERB_DIFF_NODE_INSERTED: return "node_inserted";
115
+ case HERB_DIFF_NODE_MOVED: return "node_moved";
116
+ case HERB_DIFF_NODE_REMOVED: return "node_removed";
117
+ case HERB_DIFF_NODE_REPLACED: return "node_replaced";
118
+ case HERB_DIFF_NODE_UNWRAPPED: return "node_unwrapped";
119
+ case HERB_DIFF_NODE_WRAPPED: return "node_wrapped";
120
+ case HERB_DIFF_TAG_NAME_CHANGED: return "tag_name_changed";
121
+ case HERB_DIFF_TEXT_CHANGED: return "text_changed";
122
+ }
123
+
124
+ return "unknown";
125
+ }
126
+
127
+ void herb_diff_emit_operation(
128
+ herb_diff_result_T* result,
129
+ const herb_diff_operation_type_T type,
130
+ const herb_diff_path_T path,
131
+ const AST_NODE_T* old_node,
132
+ const AST_NODE_T* new_node,
133
+ const uint32_t old_index,
134
+ const uint32_t new_index
135
+ ) {
136
+ emit_operation(result, type, path, old_node, new_node, old_index, new_index);
137
+ }
@@ -0,0 +1,207 @@
1
+ #include "../include/diff/herb_diff.h"
2
+
3
+ void herb_diff_attributes(
4
+ const hb_array_T* old_attributes,
5
+ const hb_array_T* new_attributes,
6
+ const herb_diff_path_T parent_path,
7
+ const herb_hash_map_T* old_hashes,
8
+ const herb_hash_map_T* new_hashes,
9
+ herb_diff_result_T* result
10
+ ) {
11
+ if (old_attributes == NULL && new_attributes == NULL) { return; }
12
+
13
+ if (old_attributes == NULL) {
14
+ for (size_t index = 0; index < hb_array_size(new_attributes); index++) {
15
+ const AST_NODE_T* new_attribute = (const AST_NODE_T*) hb_array_get(new_attributes, index);
16
+
17
+ herb_diff_emit_operation(
18
+ result,
19
+ HERB_DIFF_ATTRIBUTE_ADDED,
20
+ herb_diff_path_append(parent_path, (uint32_t) index),
21
+ NULL,
22
+ new_attribute,
23
+ 0,
24
+ (uint32_t) index
25
+ );
26
+ }
27
+
28
+ return;
29
+ }
30
+
31
+ if (new_attributes == NULL) {
32
+ for (size_t index = 0; index < hb_array_size(old_attributes); index++) {
33
+ const AST_NODE_T* old_attribute = (const AST_NODE_T*) hb_array_get(old_attributes, index);
34
+
35
+ herb_diff_emit_operation(
36
+ result,
37
+ HERB_DIFF_ATTRIBUTE_REMOVED,
38
+ herb_diff_path_append(parent_path, (uint32_t) index),
39
+ old_attribute,
40
+ NULL,
41
+ (uint32_t) index,
42
+ 0
43
+ );
44
+ }
45
+
46
+ return;
47
+ }
48
+
49
+ const size_t old_size = hb_array_size(old_attributes);
50
+ const size_t new_size = hb_array_size(new_attributes);
51
+
52
+ if (old_size == 0) {
53
+ for (size_t index = 0; index < new_size; index++) {
54
+ const AST_NODE_T* new_attribute = (const AST_NODE_T*) hb_array_get(new_attributes, index);
55
+
56
+ herb_diff_emit_operation(
57
+ result,
58
+ HERB_DIFF_ATTRIBUTE_ADDED,
59
+ herb_diff_path_append(parent_path, (uint32_t) index),
60
+ NULL,
61
+ new_attribute,
62
+ 0,
63
+ (uint32_t) index
64
+ );
65
+ }
66
+
67
+ return;
68
+ }
69
+
70
+ if (new_size == 0) {
71
+ for (size_t index = 0; index < old_size; index++) {
72
+ const AST_NODE_T* old_attribute = (const AST_NODE_T*) hb_array_get(old_attributes, index);
73
+
74
+ herb_diff_emit_operation(
75
+ result,
76
+ HERB_DIFF_ATTRIBUTE_REMOVED,
77
+ herb_diff_path_append(parent_path, (uint32_t) index),
78
+ old_attribute,
79
+ NULL,
80
+ (uint32_t) index,
81
+ 0
82
+ );
83
+ }
84
+
85
+ return;
86
+ }
87
+
88
+ bool* old_matched = (bool*) hb_allocator_alloc(result->allocator, old_size * sizeof(bool));
89
+
90
+ for (size_t index = 0; index < old_size; index++) {
91
+ old_matched[index] = false;
92
+ }
93
+
94
+ for (size_t new_index = 0; new_index < new_size; new_index++) {
95
+ const AST_NODE_T* new_node = (const AST_NODE_T*) hb_array_get(new_attributes, new_index);
96
+
97
+ if (new_node->type != AST_HTML_ATTRIBUTE_NODE) {
98
+ bool found = false;
99
+
100
+ for (size_t old_index = 0; old_index < old_size; old_index++) {
101
+ if (old_matched[old_index]) { continue; }
102
+
103
+ const AST_NODE_T* old_node = (const AST_NODE_T*) hb_array_get(old_attributes, old_index);
104
+
105
+ if (old_node->type == new_node->type) {
106
+ old_matched[old_index] = true;
107
+ found = true;
108
+
109
+ herb_hash_T old_hash = herb_hash_map_get(old_hashes, old_node);
110
+ herb_hash_T new_hash = herb_hash_map_get(new_hashes, new_node);
111
+
112
+ if (old_hash != new_hash) {
113
+ herb_diff_node(
114
+ old_node,
115
+ new_node,
116
+ herb_diff_path_append(parent_path, (uint32_t) new_index),
117
+ old_hashes,
118
+ new_hashes,
119
+ result
120
+ );
121
+ }
122
+
123
+ break;
124
+ }
125
+ }
126
+
127
+ if (!found) {
128
+ herb_diff_emit_operation(
129
+ result,
130
+ HERB_DIFF_ATTRIBUTE_ADDED,
131
+ herb_diff_path_append(parent_path, (uint32_t) new_index),
132
+ NULL,
133
+ new_node,
134
+ 0,
135
+ (uint32_t) new_index
136
+ );
137
+ }
138
+
139
+ continue;
140
+ }
141
+
142
+ const AST_HTML_ATTRIBUTE_NODE_T* new_attribute = (const AST_HTML_ATTRIBUTE_NODE_T*) new_node;
143
+ herb_hash_T new_name_hash = herb_hash_map_get(new_hashes, (const AST_NODE_T*) new_attribute->name);
144
+
145
+ bool found = false;
146
+
147
+ for (size_t old_index = 0; old_index < old_size; old_index++) {
148
+ if (old_matched[old_index]) { continue; }
149
+
150
+ const AST_NODE_T* old_node = (const AST_NODE_T*) hb_array_get(old_attributes, old_index);
151
+ if (old_node->type != AST_HTML_ATTRIBUTE_NODE) { continue; }
152
+
153
+ const AST_HTML_ATTRIBUTE_NODE_T* old_attribute = (const AST_HTML_ATTRIBUTE_NODE_T*) old_node;
154
+ herb_hash_T old_name_hash = herb_hash_map_get(old_hashes, (const AST_NODE_T*) old_attribute->name);
155
+
156
+ if (old_name_hash == new_name_hash) {
157
+ old_matched[old_index] = true;
158
+ found = true;
159
+
160
+ herb_hash_T old_value_hash = herb_hash_map_get(old_hashes, (const AST_NODE_T*) old_attribute->value);
161
+ herb_hash_T new_value_hash = herb_hash_map_get(new_hashes, (const AST_NODE_T*) new_attribute->value);
162
+
163
+ if (old_value_hash != new_value_hash) {
164
+ herb_diff_emit_operation(
165
+ result,
166
+ HERB_DIFF_ATTRIBUTE_VALUE_CHANGED,
167
+ herb_diff_path_append(parent_path, (uint32_t) new_index),
168
+ old_node,
169
+ new_node,
170
+ (uint32_t) old_index,
171
+ (uint32_t) new_index
172
+ );
173
+ }
174
+
175
+ break;
176
+ }
177
+ }
178
+
179
+ if (!found) {
180
+ herb_diff_emit_operation(
181
+ result,
182
+ HERB_DIFF_ATTRIBUTE_ADDED,
183
+ herb_diff_path_append(parent_path, (uint32_t) new_index),
184
+ NULL,
185
+ new_node,
186
+ 0,
187
+ (uint32_t) new_index
188
+ );
189
+ }
190
+ }
191
+
192
+ for (size_t old_index = 0; old_index < old_size; old_index++) {
193
+ if (!old_matched[old_index]) {
194
+ const AST_NODE_T* old_node = (const AST_NODE_T*) hb_array_get(old_attributes, old_index);
195
+
196
+ herb_diff_emit_operation(
197
+ result,
198
+ HERB_DIFF_ATTRIBUTE_REMOVED,
199
+ herb_diff_path_append(parent_path, (uint32_t) old_index),
200
+ old_node,
201
+ NULL,
202
+ (uint32_t) old_index,
203
+ 0
204
+ );
205
+ }
206
+ }
207
+ }