herb 0.9.4-arm-linux-gnu → 0.9.5-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.
@@ -944,6 +944,7 @@ module Herb
944
944
  # | tag_closing: Herb::Token?,
945
945
  # | prism_node: String?,
946
946
  # | body: Array[Herb::AST::Node],
947
+ # | block_arguments: Array[Herb::AST::RubyParameterNode]?,
947
948
  # | rescue_clause: Herb::AST::ERBRescueNode?,
948
949
  # | else_clause: Herb::AST::ERBElseNode?,
949
950
  # | ensure_clause: Herb::AST::ERBEnsureNode?,
@@ -962,6 +963,8 @@ module Herb
962
963
 
963
964
  attr_reader body: Array[Herb::AST::Node]
964
965
 
966
+ attr_reader block_arguments: Array[Herb::AST::RubyParameterNode]?
967
+
965
968
  attr_reader rescue_clause: Herb::AST::ERBRescueNode?
966
969
 
967
970
  attr_reader else_clause: Herb::AST::ERBElseNode?
@@ -970,8 +973,8 @@ module Herb
970
973
 
971
974
  attr_reader end_node: Herb::AST::ERBEndNode?
972
975
 
973
- # : (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, String, Array[Herb::AST::Node], Herb::AST::ERBRescueNode, Herb::AST::ERBElseNode, Herb::AST::ERBEnsureNode, Herb::AST::ERBEndNode) -> void
974
- def initialize: (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, String, Array[Herb::AST::Node], Herb::AST::ERBRescueNode, Herb::AST::ERBElseNode, Herb::AST::ERBEnsureNode, Herb::AST::ERBEndNode) -> void
976
+ # : (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, String, Array[Herb::AST::Node], Array[Herb::AST::RubyParameterNode], Herb::AST::ERBRescueNode, Herb::AST::ERBElseNode, Herb::AST::ERBEnsureNode, Herb::AST::ERBEndNode) -> void
977
+ def initialize: (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, String, Array[Herb::AST::Node], Array[Herb::AST::RubyParameterNode], Herb::AST::ERBRescueNode, Herb::AST::ERBElseNode, Herb::AST::ERBEnsureNode, Herb::AST::ERBEndNode) -> void
975
978
 
976
979
  # : () -> Prism::node?
977
980
  def deserialized_prism_node: () -> Prism::node?
@@ -1514,12 +1517,7 @@ module Herb
1514
1517
  def tree_inspect: (?indent: Integer, ?depth: Integer, ?depth_limit: Integer) -> String
1515
1518
  end
1516
1519
 
1517
- # : type serialized_erb_render_node = {
1518
- # | tag_opening: Herb::Token?,
1519
- # | content: Herb::Token?,
1520
- # | tag_closing: Herb::Token?,
1521
- # | analyzed_ruby: nil,
1522
- # | prism_node: String?,
1520
+ # : type serialized_ruby_render_keywords_node = {
1523
1521
  # | partial: Herb::Token?,
1524
1522
  # | template_path: Herb::Token?,
1525
1523
  # | layout: Herb::Token?,
@@ -1539,19 +1537,9 @@ module Herb
1539
1537
  # | content_type: Herb::Token?,
1540
1538
  # | locals: Array[Herb::AST::RubyRenderLocalNode]?,
1541
1539
  # | }
1542
- class ERBRenderNode < Node
1540
+ class RubyRenderKeywordsNode < Node
1543
1541
  include Colors
1544
1542
 
1545
- attr_reader tag_opening: Herb::Token?
1546
-
1547
- attr_reader content: Herb::Token?
1548
-
1549
- attr_reader tag_closing: Herb::Token?
1550
-
1551
- attr_reader analyzed_ruby: nil
1552
-
1553
- attr_reader prism_node: String?
1554
-
1555
1543
  attr_reader partial: Herb::Token?
1556
1544
 
1557
1545
  attr_reader template_path: Herb::Token?
@@ -1588,8 +1576,71 @@ module Herb
1588
1576
 
1589
1577
  attr_reader locals: Array[Herb::AST::RubyRenderLocalNode]?
1590
1578
 
1591
- # : (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, nil, String, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Array[Herb::AST::RubyRenderLocalNode]) -> void
1592
- def initialize: (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, nil, String, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Array[Herb::AST::RubyRenderLocalNode]) -> void
1579
+ # : (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Array[Herb::AST::RubyRenderLocalNode]) -> void
1580
+ def initialize: (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Herb::Token, Array[Herb::AST::RubyRenderLocalNode]) -> void
1581
+
1582
+ # : () -> serialized_ruby_render_keywords_node
1583
+ def to_hash: () -> serialized_ruby_render_keywords_node
1584
+
1585
+ # : (Visitor) -> void
1586
+ def accept: (Visitor) -> void
1587
+
1588
+ # : () -> Array[Herb::AST::Node?]
1589
+ def child_nodes: () -> Array[Herb::AST::Node?]
1590
+
1591
+ # : () -> Array[Herb::AST::Node]
1592
+ def compact_child_nodes: () -> Array[Herb::AST::Node]
1593
+
1594
+ # : () -> String
1595
+ def inspect: () -> String
1596
+
1597
+ # : (?indent: Integer, ?depth: Integer, ?depth_limit: Integer) -> String
1598
+ def tree_inspect: (?indent: Integer, ?depth: Integer, ?depth_limit: Integer) -> String
1599
+ end
1600
+
1601
+ # : type serialized_erb_render_node = {
1602
+ # | tag_opening: Herb::Token?,
1603
+ # | content: Herb::Token?,
1604
+ # | tag_closing: Herb::Token?,
1605
+ # | analyzed_ruby: nil,
1606
+ # | prism_node: String?,
1607
+ # | keywords: Herb::AST::RubyRenderKeywordsNode?,
1608
+ # | body: Array[Herb::AST::Node],
1609
+ # | block_arguments: Array[Herb::AST::RubyParameterNode]?,
1610
+ # | rescue_clause: Herb::AST::ERBRescueNode?,
1611
+ # | else_clause: Herb::AST::ERBElseNode?,
1612
+ # | ensure_clause: Herb::AST::ERBEnsureNode?,
1613
+ # | end_node: Herb::AST::ERBEndNode?,
1614
+ # | }
1615
+ class ERBRenderNode < Node
1616
+ include Colors
1617
+
1618
+ attr_reader tag_opening: Herb::Token?
1619
+
1620
+ attr_reader content: Herb::Token?
1621
+
1622
+ attr_reader tag_closing: Herb::Token?
1623
+
1624
+ attr_reader analyzed_ruby: nil
1625
+
1626
+ attr_reader prism_node: String?
1627
+
1628
+ attr_reader keywords: Herb::AST::RubyRenderKeywordsNode?
1629
+
1630
+ attr_reader body: Array[Herb::AST::Node]
1631
+
1632
+ attr_reader block_arguments: Array[Herb::AST::RubyParameterNode]?
1633
+
1634
+ attr_reader rescue_clause: Herb::AST::ERBRescueNode?
1635
+
1636
+ attr_reader else_clause: Herb::AST::ERBElseNode?
1637
+
1638
+ attr_reader ensure_clause: Herb::AST::ERBEnsureNode?
1639
+
1640
+ attr_reader end_node: Herb::AST::ERBEndNode?
1641
+
1642
+ # : (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, nil, String, Herb::AST::RubyRenderKeywordsNode, Array[Herb::AST::Node], Array[Herb::AST::RubyParameterNode], Herb::AST::ERBRescueNode, Herb::AST::ERBElseNode, Herb::AST::ERBEnsureNode, Herb::AST::ERBEndNode) -> void
1643
+ def initialize: (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, nil, String, Herb::AST::RubyRenderKeywordsNode, Array[Herb::AST::Node], Array[Herb::AST::RubyParameterNode], Herb::AST::ERBRescueNode, Herb::AST::ERBElseNode, Herb::AST::ERBEnsureNode, Herb::AST::ERBEndNode) -> void
1593
1644
 
1594
1645
  # : () -> Prism::node?
1595
1646
  def deserialized_prism_node: () -> Prism::node?
@@ -1613,28 +1664,28 @@ module Herb
1613
1664
  def tree_inspect: (?indent: Integer, ?depth: Integer, ?depth_limit: Integer) -> String
1614
1665
  end
1615
1666
 
1616
- # : type serialized_ruby_strict_local_node = {
1667
+ # : type serialized_ruby_parameter_node = {
1617
1668
  # | name: Herb::Token?,
1618
1669
  # | default_value: Herb::AST::RubyLiteralNode?,
1670
+ # | kind: String?,
1619
1671
  # | required: bool,
1620
- # | double_splat: bool,
1621
1672
  # | }
1622
- class RubyStrictLocalNode < Node
1673
+ class RubyParameterNode < Node
1623
1674
  include Colors
1624
1675
 
1625
1676
  attr_reader name: Herb::Token?
1626
1677
 
1627
1678
  attr_reader default_value: Herb::AST::RubyLiteralNode?
1628
1679
 
1629
- attr_reader required: bool
1680
+ attr_reader kind: String?
1630
1681
 
1631
- attr_reader double_splat: bool
1682
+ attr_reader required: bool
1632
1683
 
1633
- # : (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::AST::RubyLiteralNode, bool, bool) -> void
1634
- def initialize: (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::AST::RubyLiteralNode, bool, bool) -> void
1684
+ # : (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::AST::RubyLiteralNode, String, bool) -> void
1685
+ def initialize: (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::AST::RubyLiteralNode, String, bool) -> void
1635
1686
 
1636
- # : () -> serialized_ruby_strict_local_node
1637
- def to_hash: () -> serialized_ruby_strict_local_node
1687
+ # : () -> serialized_ruby_parameter_node
1688
+ def to_hash: () -> serialized_ruby_parameter_node
1638
1689
 
1639
1690
  # : (Visitor) -> void
1640
1691
  def accept: (Visitor) -> void
@@ -1658,7 +1709,7 @@ module Herb
1658
1709
  # | tag_closing: Herb::Token?,
1659
1710
  # | analyzed_ruby: nil,
1660
1711
  # | prism_node: String?,
1661
- # | locals: Array[Herb::AST::RubyStrictLocalNode]?,
1712
+ # | locals: Array[Herb::AST::RubyParameterNode]?,
1662
1713
  # | }
1663
1714
  class ERBStrictLocalsNode < Node
1664
1715
  include Colors
@@ -1673,10 +1724,10 @@ module Herb
1673
1724
 
1674
1725
  attr_reader prism_node: String?
1675
1726
 
1676
- attr_reader locals: Array[Herb::AST::RubyStrictLocalNode]?
1727
+ attr_reader locals: Array[Herb::AST::RubyParameterNode]?
1677
1728
 
1678
- # : (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, nil, String, Array[Herb::AST::RubyStrictLocalNode]) -> void
1679
- def initialize: (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, nil, String, Array[Herb::AST::RubyStrictLocalNode]) -> void
1729
+ # : (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, nil, String, Array[Herb::AST::RubyParameterNode]) -> void
1730
+ def initialize: (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, nil, String, Array[Herb::AST::RubyParameterNode]) -> void
1680
1731
 
1681
1732
  # : () -> Prism::node?
1682
1733
  def deserialized_prism_node: () -> Prism::node?
data/sig/herb/visitor.rbs CHANGED
@@ -130,11 +130,14 @@ module Herb
130
130
  # : (Herb::AST::RubyRenderLocalNode) -> void
131
131
  def visit_ruby_render_local_node: (Herb::AST::RubyRenderLocalNode) -> void
132
132
 
133
+ # : (Herb::AST::RubyRenderKeywordsNode) -> void
134
+ def visit_ruby_render_keywords_node: (Herb::AST::RubyRenderKeywordsNode) -> void
135
+
133
136
  # : (Herb::AST::ERBRenderNode) -> void
134
137
  def visit_erb_render_node: (Herb::AST::ERBRenderNode) -> void
135
138
 
136
- # : (Herb::AST::RubyStrictLocalNode) -> void
137
- def visit_ruby_strict_local_node: (Herb::AST::RubyStrictLocalNode) -> void
139
+ # : (Herb::AST::RubyParameterNode) -> void
140
+ def visit_ruby_parameter_node: (Herb::AST::RubyParameterNode) -> void
138
141
 
139
142
  # : (Herb::AST::ERBStrictLocalsNode) -> void
140
143
  def visit_erb_strict_locals_node: (Herb::AST::ERBStrictLocalsNode) -> void
@@ -170,6 +170,7 @@ module Herb
170
170
  tag_closing: Herb::Token,
171
171
  prism_node: String,
172
172
  body: Array[Herb::AST::Node],
173
+ block_arguments: Array[Herb::AST::RubyParameterNode],
173
174
  rescue_clause: Herb::AST::ERBRescueNode,
174
175
  else_clause: Herb::AST::ERBElseNode,
175
176
  ensure_clause: Herb::AST::ERBEnsureNode,
@@ -276,12 +277,7 @@ module Herb
276
277
  value: Herb::AST::RubyLiteralNode,
277
278
  }
278
279
 
279
- type serialized_erb_render_node = serialized_node & {
280
- tag_opening: Herb::Token,
281
- content: Herb::Token,
282
- tag_closing: Herb::Token,
283
- analyzed_ruby: nil,
284
- prism_node: String,
280
+ type serialized_ruby_render_keywords_node = serialized_node & {
285
281
  partial: Herb::Token,
286
282
  template_path: Herb::Token,
287
283
  layout: Herb::Token,
@@ -302,11 +298,26 @@ module Herb
302
298
  locals: Array[Herb::AST::RubyRenderLocalNode],
303
299
  }
304
300
 
305
- type serialized_ruby_strict_local_node = serialized_node & {
301
+ type serialized_erb_render_node = serialized_node & {
302
+ tag_opening: Herb::Token,
303
+ content: Herb::Token,
304
+ tag_closing: Herb::Token,
305
+ analyzed_ruby: nil,
306
+ prism_node: String,
307
+ keywords: Herb::AST::RubyRenderKeywordsNode,
308
+ body: Array[Herb::AST::Node],
309
+ block_arguments: Array[Herb::AST::RubyParameterNode],
310
+ rescue_clause: Herb::AST::ERBRescueNode,
311
+ else_clause: Herb::AST::ERBElseNode,
312
+ ensure_clause: Herb::AST::ERBEnsureNode,
313
+ end_node: Herb::AST::ERBEndNode,
314
+ }
315
+
316
+ type serialized_ruby_parameter_node = serialized_node & {
306
317
  name: Herb::Token,
307
318
  default_value: Herb::AST::RubyLiteralNode,
319
+ kind: String,
308
320
  required: bool,
309
- double_splat: bool,
310
321
  }
311
322
 
312
323
  type serialized_erb_strict_locals_node = serialized_node & {
@@ -315,7 +326,7 @@ module Herb
315
326
  tag_closing: Herb::Token,
316
327
  analyzed_ruby: nil,
317
328
  prism_node: String,
318
- locals: Array[Herb::AST::RubyStrictLocalNode],
329
+ locals: Array[Herb::AST::RubyParameterNode],
319
330
  }
320
331
 
321
332
  type serialized_erb_yield_node = serialized_node & {
@@ -1,4 +1,9 @@
1
1
  #include "../../include/analyze/action_view/tag_helper_handler.h"
2
+ #include "../../include/analyze/action_view/tag_helper_node_builders.h"
3
+ #include "../../include/ast/ast_nodes.h"
4
+ #include "../../include/lib/hb_array.h"
5
+ #include "../../include/lib/hb_string.h"
6
+ #include "../../include/visitor.h"
2
7
 
3
8
  #include <prism.h>
4
9
  #include <stdbool.h>
@@ -45,6 +50,39 @@ bool javascript_tag_supports_block(void) {
45
50
  return true;
46
51
  }
47
52
 
53
+ bool wrap_javascript_tag_body_visitor(const AST_NODE_T* node, void* data) {
54
+ hb_allocator_T* allocator = (hb_allocator_T*) data;
55
+
56
+ if (node == NULL || node->type != AST_HTML_ELEMENT_NODE) { return true; }
57
+
58
+ AST_HTML_ELEMENT_NODE_T* element = (AST_HTML_ELEMENT_NODE_T*) node;
59
+
60
+ if (!hb_string_equals(element->element_source, hb_string("ActionView::Helpers::JavaScriptHelper#javascript_tag"))) {
61
+ return true;
62
+ }
63
+
64
+ if (element->body == NULL || hb_array_size(element->body) == 0) { return false; }
65
+
66
+ for (size_t i = 0; i < hb_array_size(element->body); i++) {
67
+ AST_NODE_T* child = (AST_NODE_T*) hb_array_get(element->body, i);
68
+ if (child && child->type == AST_CDATA_NODE) { return false; }
69
+ }
70
+
71
+ hb_array_T* cdata_children = hb_array_init(hb_array_size(element->body), allocator);
72
+
73
+ for (size_t i = 0; i < hb_array_size(element->body); i++) {
74
+ hb_array_append(cdata_children, hb_array_get(element->body, i));
75
+ }
76
+
77
+ AST_CDATA_NODE_T* cdata_node =
78
+ create_javascript_cdata_node(cdata_children, element->base.location.start, element->base.location.end, allocator);
79
+
80
+ element->body->size = 0;
81
+ hb_array_append(element->body, (AST_NODE_T*) cdata_node);
82
+
83
+ return false;
84
+ }
85
+
48
86
  const tag_helper_handler_T javascript_tag_handler = {
49
87
  .name = "javascript_tag",
50
88
  .source = HB_STRING_LITERAL("ActionView::Helpers::JavaScriptHelper#javascript_tag"),
@@ -124,7 +124,7 @@ AST_HTML_ATTRIBUTE_NODE_T* create_html_attribute_node_precise(
124
124
  open_quote,
125
125
  value_children,
126
126
  close_quote,
127
- positions->quoted,
127
+ true,
128
128
  positions->value_start,
129
129
  positions->value_end,
130
130
  hb_array_init(0, allocator),
@@ -179,7 +179,7 @@ AST_HTML_ATTRIBUTE_NODE_T* create_html_attribute_with_ruby_literal_precise(
179
179
  NULL,
180
180
  value_children,
181
181
  NULL,
182
- false,
182
+ true,
183
183
  positions->content_start,
184
184
  positions->content_end,
185
185
  hb_array_init(0, allocator),
@@ -385,3 +385,24 @@ void append_body_content_node(
385
385
  if (text_node) { hb_array_append(body, (AST_NODE_T*) text_node); }
386
386
  }
387
387
  }
388
+
389
+ AST_CDATA_NODE_T* create_javascript_cdata_node(
390
+ hb_array_T* children,
391
+ position_T start,
392
+ position_T end,
393
+ hb_allocator_T* allocator
394
+ ) {
395
+ token_T* cdata_opening = create_synthetic_token(allocator, "\n//<![CDATA[\n", TOKEN_CDATA_START, start, end);
396
+
397
+ token_T* cdata_closing = create_synthetic_token(allocator, "\n//]]>\n", TOKEN_CDATA_END, start, end);
398
+
399
+ return ast_cdata_node_init(
400
+ cdata_opening,
401
+ children,
402
+ cdata_closing,
403
+ start,
404
+ end,
405
+ hb_array_init(0, allocator),
406
+ allocator
407
+ );
408
+ }
@@ -639,7 +639,15 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
639
639
  id_is_ruby_expression ? create_html_attribute_with_ruby_literal("id", id_value, id_start, id_end, allocator)
640
640
  : create_html_attribute_node("id", id_value, id_start, id_end, allocator);
641
641
 
642
- if (id_attribute) { attributes = prepend_attribute(attributes, (AST_NODE_T*) id_attribute, allocator); }
642
+ if (id_attribute) {
643
+ AST_NODE_T* src_node = remove_attribute_by_name(attributes, "src");
644
+ AST_NODE_T* target_node = remove_attribute_by_name(attributes, "target");
645
+
646
+ hb_array_append(attributes, (AST_NODE_T*) id_attribute);
647
+
648
+ if (src_node) { hb_array_append(attributes, src_node); }
649
+ if (target_node) { hb_array_append(attributes, target_node); }
650
+ }
643
651
 
644
652
  hb_allocator_dealloc(allocator, id_value);
645
653
  }
@@ -679,7 +687,7 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
679
687
  ? create_html_attribute_node("src", source_attribute_value, source_start, source_end, allocator)
680
688
  : create_html_attribute_with_ruby_literal("src", source_attribute_value, source_start, source_end, allocator);
681
689
 
682
- if (source_attribute) { attributes = prepend_attribute(attributes, (AST_NODE_T*) source_attribute, allocator); }
690
+ if (source_attribute) { hb_array_append(attributes, (AST_NODE_T*) source_attribute); }
683
691
 
684
692
  if (source_attribute_value != source_value) { hb_allocator_dealloc(allocator, source_attribute_value); }
685
693
  hb_allocator_dealloc(allocator, source_value);
@@ -723,7 +731,7 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
723
731
  ? create_html_attribute_node("src", source_attribute_value, source_start, source_end, allocator)
724
732
  : create_html_attribute_with_ruby_literal("src", source_attribute_value, source_start, source_end, allocator);
725
733
 
726
- if (source_attribute) { attributes = prepend_attribute(attributes, (AST_NODE_T*) source_attribute, allocator); }
734
+ if (source_attribute) { hb_array_append(attributes, (AST_NODE_T*) source_attribute); }
727
735
  if (source_attribute_value != source_value) { hb_allocator_dealloc(allocator, source_attribute_value); }
728
736
 
729
737
  hb_allocator_dealloc(allocator, source_value);
@@ -798,14 +806,37 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
798
806
  );
799
807
  }
800
808
 
801
- append_body_content_node(
802
- body,
803
- helper_content,
804
- content_is_ruby_expression,
805
- erb_node->base.location.start,
806
- erb_node->base.location.end,
807
- allocator
808
- );
809
+ if (string_equals(handler->name, "javascript_tag")) {
810
+ hb_array_T* cdata_children = hb_array_init(1, allocator);
811
+
812
+ append_body_content_node(
813
+ cdata_children,
814
+ helper_content,
815
+ content_is_ruby_expression,
816
+ erb_node->base.location.start,
817
+ erb_node->base.location.end,
818
+ allocator
819
+ );
820
+
821
+ AST_CDATA_NODE_T* cdata_node = create_javascript_cdata_node(
822
+ cdata_children,
823
+ erb_node->base.location.start,
824
+ erb_node->base.location.end,
825
+ allocator
826
+ );
827
+
828
+ if (cdata_node) { hb_array_append(body, (AST_NODE_T*) cdata_node); }
829
+ } else {
830
+ append_body_content_node(
831
+ body,
832
+ helper_content,
833
+ content_is_ruby_expression,
834
+ erb_node->base.location.start,
835
+ erb_node->base.location.end,
836
+ allocator
837
+ );
838
+ }
839
+
809
840
  hb_allocator_dealloc(allocator, helper_content);
810
841
  }
811
842
 
@@ -1117,7 +1148,7 @@ static AST_NODE_T* transform_erb_block_to_tag_helper(
1117
1148
  AST_HTML_ATTRIBUTE_NODE_T* href_attribute =
1118
1149
  create_href_attribute(href, href_is_ruby_expression, href_start, href_end, allocator);
1119
1150
 
1120
- if (href_attribute) { attributes = prepend_attribute(attributes, (AST_NODE_T*) href_attribute, allocator); }
1151
+ if (href_attribute) { hb_array_append(attributes, (AST_NODE_T*) href_attribute); }
1121
1152
 
1122
1153
  hb_allocator_dealloc(allocator, href);
1123
1154
  }
@@ -1138,7 +1169,15 @@ static AST_NODE_T* transform_erb_block_to_tag_helper(
1138
1169
  id_is_ruby_expression ? create_html_attribute_with_ruby_literal("id", id_value, id_start, id_end, allocator)
1139
1170
  : create_html_attribute_node("id", id_value, id_start, id_end, allocator);
1140
1171
 
1141
- if (id_attribute) { attributes = prepend_attribute(attributes, (AST_NODE_T*) id_attribute, allocator); }
1172
+ if (id_attribute) {
1173
+ AST_NODE_T* src_node = remove_attribute_by_name(attributes, "src");
1174
+ AST_NODE_T* target_node = remove_attribute_by_name(attributes, "target");
1175
+
1176
+ hb_array_append(attributes, (AST_NODE_T*) id_attribute);
1177
+
1178
+ if (src_node) { hb_array_append(attributes, src_node); }
1179
+ if (target_node) { hb_array_append(attributes, target_node); }
1180
+ }
1142
1181
 
1143
1182
  hb_allocator_dealloc(allocator, id_value);
1144
1183
  }
@@ -1395,7 +1434,7 @@ static AST_NODE_T* transform_link_to_helper(
1395
1434
  AST_HTML_ATTRIBUTE_NODE_T* href_attribute =
1396
1435
  create_href_attribute(href, href_is_ruby_expression, href_start, href_end, allocator);
1397
1436
 
1398
- if (href_attribute) { attributes = prepend_attribute(attributes, (AST_NODE_T*) href_attribute, allocator); }
1437
+ if (href_attribute) { hb_array_append(attributes, (AST_NODE_T*) href_attribute); }
1399
1438
  if (!info->content) {
1400
1439
  href_for_body = hb_allocator_strdup(allocator, href);
1401
1440
  href_for_body_is_ruby_expression = href_is_ruby_expression;
@@ -736,12 +736,32 @@ static size_t process_block_structure(
736
736
  hb_array_T* block_errors = erb_node->base.errors;
737
737
  erb_node->base.errors = NULL;
738
738
 
739
+ // Filter out "incomplete block" Prism errors since we've matched the block with its end tag.
740
+ if (block_errors) {
741
+ for (size_t error_index = hb_array_size(block_errors); error_index > 0; error_index--) {
742
+ ERROR_T* error = hb_array_get(block_errors, error_index - 1);
743
+ if (!error || error->type != RUBY_PARSE_ERROR) { continue; }
744
+
745
+ RUBY_PARSE_ERROR_T* parse_error = (RUBY_PARSE_ERROR_T*) error;
746
+
747
+ if (string_equals(parse_error->diagnostic_id.data, "block_term_end")
748
+ || string_equals(parse_error->diagnostic_id.data, "block_term_brace")
749
+ || string_equals(parse_error->diagnostic_id.data, "unexpected_token_close_context")) {
750
+ hb_array_remove(block_errors, error_index - 1);
751
+ }
752
+ }
753
+ }
754
+
755
+ hb_array_T* block_arguments =
756
+ extract_block_arguments_from_erb_node(erb_node, context->source, block_errors, allocator);
757
+
739
758
  AST_ERB_BLOCK_NODE_T* block_node = ast_erb_block_node_init(
740
759
  erb_node->tag_opening,
741
760
  erb_node->content,
742
761
  erb_node->tag_closing,
743
762
  HERB_PRISM_NODE_EMPTY,
744
763
  children,
764
+ block_arguments,
745
765
  rescue_clause,
746
766
  else_clause,
747
767
  ensure_clause,
@@ -942,6 +962,7 @@ hb_array_T* get_node_children_array(const AST_NODE_T* node) {
942
962
  case AST_ERB_ENSURE_NODE: return ((AST_ERB_ENSURE_NODE_T*) node)->statements;
943
963
  case AST_ERB_CASE_NODE: return ((AST_ERB_CASE_NODE_T*) node)->children;
944
964
  case AST_ERB_WHEN_NODE: return ((AST_ERB_WHEN_NODE_T*) node)->statements;
965
+ case AST_ERB_RENDER_NODE: return ((AST_ERB_RENDER_NODE_T*) node)->body;
945
966
  default: return NULL;
946
967
  }
947
968
  }