herb 0.9.1-aarch64-linux-gnu → 0.9.3-aarch64-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 (171) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/config.yml +125 -0
  4. data/ext/herb/error_helpers.c +172 -2
  5. data/ext/herb/extconf.rb +6 -0
  6. data/ext/herb/extension.c +16 -2
  7. data/ext/herb/extension_helpers.c +6 -5
  8. data/ext/herb/extension_helpers.h +4 -4
  9. data/ext/herb/nodes.c +89 -3
  10. data/lib/herb/3.0/herb.so +0 -0
  11. data/lib/herb/3.1/herb.so +0 -0
  12. data/lib/herb/3.2/herb.so +0 -0
  13. data/lib/herb/3.3/herb.so +0 -0
  14. data/lib/herb/3.4/herb.so +0 -0
  15. data/lib/herb/4.0/herb.so +0 -0
  16. data/lib/herb/ast/erb_content_node.rb +32 -0
  17. data/lib/herb/ast/nodes.rb +244 -3
  18. data/lib/herb/cli.rb +12 -2
  19. data/lib/herb/engine/compiler.rb +136 -97
  20. data/lib/herb/engine/validators/security_validator.rb +40 -0
  21. data/lib/herb/engine.rb +21 -0
  22. data/lib/herb/errors.rb +268 -0
  23. data/lib/herb/parser_options.rb +7 -2
  24. data/lib/herb/version.rb +1 -1
  25. data/lib/herb/visitor.rb +82 -0
  26. data/lib/herb.rb +1 -0
  27. data/sig/herb/ast/erb_content_node.rbs +13 -0
  28. data/sig/herb/ast/nodes.rbs +98 -2
  29. data/sig/herb/engine/compiler.rbs +18 -3
  30. data/sig/herb/engine/validators/security_validator.rbs +4 -0
  31. data/sig/herb/engine.rbs +4 -0
  32. data/sig/herb/errors.rbs +122 -0
  33. data/sig/herb/parser_options.rbs +6 -2
  34. data/sig/herb/visitor.rbs +12 -0
  35. data/sig/serialized_ast_errors.rbs +29 -0
  36. data/sig/serialized_ast_nodes.rbs +19 -0
  37. data/src/analyze/action_view/attribute_extraction_helpers.c +425 -87
  38. data/src/analyze/action_view/image_tag.c +87 -0
  39. data/src/analyze/action_view/javascript_include_tag.c +102 -0
  40. data/src/analyze/action_view/javascript_tag.c +55 -0
  41. data/src/analyze/action_view/registry.c +10 -3
  42. data/src/analyze/action_view/tag.c +19 -2
  43. data/src/analyze/action_view/tag_helper_node_builders.c +119 -37
  44. data/src/analyze/action_view/tag_helpers.c +1033 -32
  45. data/src/analyze/analyze.c +165 -10
  46. data/src/analyze/{helpers.c → analyze_helpers.c} +1 -1
  47. data/src/analyze/analyzed_ruby.c +1 -1
  48. data/src/analyze/builders.c +11 -8
  49. data/src/analyze/conditional_elements.c +6 -7
  50. data/src/analyze/conditional_open_tags.c +6 -7
  51. data/src/analyze/control_type.c +4 -2
  52. data/src/analyze/invalid_structures.c +5 -5
  53. data/src/analyze/missing_end.c +2 -2
  54. data/src/analyze/parse_errors.c +5 -5
  55. data/src/analyze/prism_annotate.c +7 -7
  56. data/src/analyze/render_nodes.c +6 -26
  57. data/src/analyze/strict_locals.c +637 -0
  58. data/src/analyze/transform.c +7 -0
  59. data/src/{ast_node.c → ast/ast_node.c} +8 -8
  60. data/src/{ast_nodes.c → ast/ast_nodes.c} +82 -11
  61. data/src/{ast_pretty_print.c → ast/ast_pretty_print.c} +113 -9
  62. data/src/{pretty_print.c → ast/pretty_print.c} +9 -9
  63. data/src/errors.c +398 -8
  64. data/src/extract.c +5 -5
  65. data/src/herb.c +15 -5
  66. data/src/include/analyze/action_view/attribute_extraction_helpers.h +3 -1
  67. data/src/include/analyze/action_view/tag_helper_handler.h +3 -3
  68. data/src/include/analyze/action_view/tag_helper_node_builders.h +34 -5
  69. data/src/include/analyze/action_view/tag_helpers.h +4 -3
  70. data/src/include/analyze/analyze.h +6 -4
  71. data/src/include/analyze/analyzed_ruby.h +2 -2
  72. data/src/include/analyze/builders.h +4 -4
  73. data/src/include/analyze/conditional_elements.h +2 -2
  74. data/src/include/analyze/conditional_open_tags.h +2 -2
  75. data/src/include/analyze/control_type.h +1 -1
  76. data/src/include/analyze/helpers.h +2 -2
  77. data/src/include/analyze/invalid_structures.h +1 -1
  78. data/src/include/analyze/prism_annotate.h +2 -2
  79. data/src/include/analyze/render_nodes.h +1 -1
  80. data/src/include/analyze/strict_locals.h +11 -0
  81. data/src/include/{ast_node.h → ast/ast_node.h} +4 -4
  82. data/src/include/{ast_nodes.h → ast/ast_nodes.h} +38 -14
  83. data/src/include/{ast_pretty_print.h → ast/ast_pretty_print.h} +3 -3
  84. data/src/include/{pretty_print.h → ast/pretty_print.h} +4 -4
  85. data/src/include/errors.h +65 -7
  86. data/src/include/extract.h +2 -2
  87. data/src/include/herb.h +5 -5
  88. data/src/include/{lex_helpers.h → lexer/lex_helpers.h} +5 -5
  89. data/src/include/{lexer.h → lexer/lexer.h} +1 -1
  90. data/src/include/{lexer_peek_helpers.h → lexer/lexer_peek_helpers.h} +2 -2
  91. data/src/include/{lexer_struct.h → lexer/lexer_struct.h} +2 -2
  92. data/src/include/{token.h → lexer/token.h} +3 -3
  93. data/src/include/{token_matchers.h → lexer/token_matchers.h} +1 -1
  94. data/src/include/{token_struct.h → lexer/token_struct.h} +3 -3
  95. data/src/include/{util → lib}/hb_foreach.h +1 -1
  96. data/src/include/{util → lib}/hb_string.h +5 -1
  97. data/src/include/{location.h → location/location.h} +1 -1
  98. data/src/include/parser/dot_notation.h +12 -0
  99. data/src/include/{parser.h → parser/parser.h} +11 -4
  100. data/src/include/{parser_helpers.h → parser/parser_helpers.h} +6 -6
  101. data/src/include/{prism_context.h → prism/prism_context.h} +2 -2
  102. data/src/include/{prism_helpers.h → prism/prism_helpers.h} +6 -6
  103. data/src/include/{html_util.h → util/html_util.h} +2 -1
  104. data/src/include/util/ruby_util.h +9 -0
  105. data/src/include/{utf8.h → util/utf8.h} +1 -1
  106. data/src/include/{util.h → util/util.h} +1 -1
  107. data/src/include/version.h +1 -1
  108. data/src/include/visitor.h +3 -3
  109. data/src/{lexer_peek_helpers.c → lexer/lexer_peek_helpers.c} +3 -3
  110. data/src/{token.c → lexer/token.c} +8 -8
  111. data/src/{token_matchers.c → lexer/token_matchers.c} +2 -2
  112. data/src/lexer.c +6 -6
  113. data/src/{util → lib}/hb_allocator.c +2 -2
  114. data/src/{util → lib}/hb_arena.c +4 -8
  115. data/src/{util → lib}/hb_arena_debug.c +2 -2
  116. data/src/{util → lib}/hb_array.c +2 -2
  117. data/src/{util → lib}/hb_buffer.c +2 -2
  118. data/src/{util → lib}/hb_narray.c +1 -1
  119. data/src/{util → lib}/hb_string.c +2 -2
  120. data/src/{location.c → location/location.c} +2 -2
  121. data/src/{position.c → location/position.c} +2 -2
  122. data/src/{range.c → location/range.c} +1 -1
  123. data/src/main.c +11 -11
  124. data/src/parser/dot_notation.c +100 -0
  125. data/src/{parser_match_tags.c → parser/match_tags.c} +34 -5
  126. data/src/{parser_helpers.c → parser/parser_helpers.c} +10 -10
  127. data/src/parser.c +68 -32
  128. data/src/{prism_helpers.c → prism/prism_helpers.c} +7 -7
  129. data/src/{ruby_parser.c → prism/ruby_parser.c} +1 -1
  130. data/src/{html_util.c → util/html_util.c} +54 -4
  131. data/src/{io.c → util/io.c} +3 -3
  132. data/src/util/ruby_util.c +42 -0
  133. data/src/{utf8.c → util/utf8.c} +2 -2
  134. data/src/{util.c → util/util.c} +4 -4
  135. data/src/visitor.c +35 -3
  136. data/templates/ext/herb/error_helpers.c.erb +2 -2
  137. data/templates/ext/herb/nodes.c.erb +1 -1
  138. data/templates/java/error_helpers.c.erb +1 -1
  139. data/templates/java/error_helpers.h.erb +2 -2
  140. data/templates/java/nodes.c.erb +4 -4
  141. data/templates/java/nodes.h.erb +1 -1
  142. data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +4 -4
  143. data/templates/javascript/packages/node/extension/nodes.cpp.erb +4 -4
  144. data/templates/lib/herb/visitor.rb.erb +14 -0
  145. data/templates/src/analyze/missing_end.c.erb +2 -2
  146. data/templates/src/{ast_nodes.c.erb → ast/ast_nodes.c.erb} +9 -9
  147. data/templates/src/{ast_pretty_print.c.erb → ast/ast_pretty_print.c.erb} +8 -8
  148. data/templates/src/errors.c.erb +8 -8
  149. data/templates/src/include/{ast_nodes.h.erb → ast/ast_nodes.h.erb} +11 -12
  150. data/templates/src/include/{ast_pretty_print.h.erb → ast/ast_pretty_print.h.erb} +2 -2
  151. data/templates/src/include/errors.h.erb +7 -7
  152. data/templates/src/{parser_match_tags.c.erb → parser/match_tags.c.erb} +4 -4
  153. data/templates/src/visitor.c.erb +3 -3
  154. data/templates/wasm/error_helpers.cpp.erb +4 -4
  155. data/templates/wasm/nodes.cpp.erb +5 -5
  156. metadata +78 -68
  157. data/src/include/element_source.h +0 -10
  158. /data/src/include/{util → lib}/hb_allocator.h +0 -0
  159. /data/src/include/{util → lib}/hb_arena.h +0 -0
  160. /data/src/include/{util → lib}/hb_arena_debug.h +0 -0
  161. /data/src/include/{util → lib}/hb_array.h +0 -0
  162. /data/src/include/{util → lib}/hb_buffer.h +0 -0
  163. /data/src/include/{util → lib}/hb_narray.h +0 -0
  164. /data/src/include/{util → lib}/string.h +0 -0
  165. /data/src/include/{position.h → location/position.h} +0 -0
  166. /data/src/include/{range.h → location/range.h} +0 -0
  167. /data/src/include/{herb_prism_node.h → prism/herb_prism_node.h} +0 -0
  168. /data/src/include/{prism_serialized.h → prism/prism_serialized.h} +0 -0
  169. /data/src/include/{ruby_parser.h → prism/ruby_parser.h} +0 -0
  170. /data/src/include/{io.h → util/io.h} +0 -0
  171. /data/templates/src/include/{util → lib}/hb_foreach.h.erb +0 -0
@@ -2128,6 +2128,9 @@ module Herb
2128
2128
  #| tag_closing: Herb::Token?,
2129
2129
  #| prism_node: String?,
2130
2130
  #| body: Array[Herb::AST::Node],
2131
+ #| rescue_clause: Herb::AST::ERBRescueNode?,
2132
+ #| else_clause: Herb::AST::ERBElseNode?,
2133
+ #| ensure_clause: Herb::AST::ERBEnsureNode?,
2131
2134
  #| end_node: Herb::AST::ERBEndNode?,
2132
2135
  #| }
2133
2136
  class ERBBlockNode < Node
@@ -2138,16 +2141,22 @@ module Herb
2138
2141
  attr_reader :tag_closing #: Herb::Token?
2139
2142
  attr_reader :prism_node #: String?
2140
2143
  attr_reader :body #: Array[Herb::AST::Node]
2144
+ attr_reader :rescue_clause #: Herb::AST::ERBRescueNode?
2145
+ attr_reader :else_clause #: Herb::AST::ERBElseNode?
2146
+ attr_reader :ensure_clause #: Herb::AST::ERBEnsureNode?
2141
2147
  attr_reader :end_node #: Herb::AST::ERBEndNode?
2142
2148
 
2143
- #: (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, String, Array[Herb::AST::Node], Herb::AST::ERBEndNode) -> void
2144
- def initialize(type, location, errors, tag_opening, content, tag_closing, prism_node, body, end_node)
2149
+ #: (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
2150
+ def initialize(type, location, errors, tag_opening, content, tag_closing, prism_node, body, rescue_clause, else_clause, ensure_clause, end_node)
2145
2151
  super(type, location, errors)
2146
2152
  @tag_opening = tag_opening
2147
2153
  @content = content
2148
2154
  @tag_closing = tag_closing
2149
2155
  @prism_node = prism_node
2150
2156
  @body = body
2157
+ @rescue_clause = rescue_clause
2158
+ @else_clause = else_clause
2159
+ @ensure_clause = ensure_clause
2151
2160
  @end_node = end_node
2152
2161
  end
2153
2162
 
@@ -2175,6 +2184,9 @@ module Herb
2175
2184
  tag_closing: tag_closing,
2176
2185
  prism_node: prism_node,
2177
2186
  body: body,
2187
+ rescue_clause: rescue_clause,
2188
+ else_clause: else_clause,
2189
+ ensure_clause: ensure_clause,
2178
2190
  end_node: end_node,
2179
2191
  }) #: Herb::serialized_erb_block_node
2180
2192
  end
@@ -2186,7 +2198,7 @@ module Herb
2186
2198
 
2187
2199
  #: () -> Array[Herb::AST::Node?]
2188
2200
  def child_nodes
2189
- [*(body || []), end_node]
2201
+ [*(body || []), rescue_clause, else_clause, ensure_clause, end_node]
2190
2202
  end
2191
2203
 
2192
2204
  #: () -> Array[Herb::AST::Node]
@@ -2230,6 +2242,30 @@ module Herb
2230
2242
  end
2231
2243
  output += white("├── body: ")
2232
2244
  output += inspect_array(body, prefix: "│ ", indent: indent, depth: depth + 1, depth_limit: depth_limit)
2245
+ output += white("├── rescue_clause: ")
2246
+ if rescue_clause
2247
+ output += "\n"
2248
+ output += "│ └── "
2249
+ output += rescue_clause.tree_inspect(indent: indent, depth: depth + 1, depth_limit: depth_limit).gsub(/^/, " " * (indent + 1)).lstrip.gsub(/^/, "│ ").delete_prefix("│ ")
2250
+ else
2251
+ output += magenta("∅\n")
2252
+ end
2253
+ output += white("├── else_clause: ")
2254
+ if else_clause
2255
+ output += "\n"
2256
+ output += "│ └── "
2257
+ output += else_clause.tree_inspect(indent: indent, depth: depth + 1, depth_limit: depth_limit).gsub(/^/, " " * (indent + 1)).lstrip.gsub(/^/, "│ ").delete_prefix("│ ")
2258
+ else
2259
+ output += magenta("∅\n")
2260
+ end
2261
+ output += white("├── ensure_clause: ")
2262
+ if ensure_clause
2263
+ output += "\n"
2264
+ output += "│ └── "
2265
+ output += ensure_clause.tree_inspect(indent: indent, depth: depth + 1, depth_limit: depth_limit).gsub(/^/, " " * (indent + 1)).lstrip.gsub(/^/, "│ ").delete_prefix("│ ")
2266
+ else
2267
+ output += magenta("∅\n")
2268
+ end
2233
2269
  output += white("└── end_node: ")
2234
2270
  if end_node
2235
2271
  output += "\n"
@@ -3773,6 +3809,211 @@ module Herb
3773
3809
  end
3774
3810
  end
3775
3811
 
3812
+ #: type serialized_ruby_strict_local_node = {
3813
+ #| name: Herb::Token?,
3814
+ #| default_value: Herb::AST::RubyLiteralNode?,
3815
+ #| required: bool,
3816
+ #| double_splat: bool,
3817
+ #| }
3818
+ class RubyStrictLocalNode < Node
3819
+ include Colors
3820
+
3821
+ attr_reader :name #: Herb::Token?
3822
+ attr_reader :default_value #: Herb::AST::RubyLiteralNode?
3823
+ attr_reader :required #: bool
3824
+ attr_reader :double_splat #: bool
3825
+
3826
+ #: (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::AST::RubyLiteralNode, bool, bool) -> void
3827
+ def initialize(type, location, errors, name, default_value, required, double_splat)
3828
+ super(type, location, errors)
3829
+ @name = name
3830
+ @default_value = default_value
3831
+ @required = required
3832
+ @double_splat = double_splat
3833
+ end
3834
+
3835
+ #: () -> serialized_ruby_strict_local_node
3836
+ def to_hash
3837
+ super.merge({
3838
+ name: name,
3839
+ default_value: default_value,
3840
+ required: required,
3841
+ double_splat: double_splat,
3842
+ }) #: Herb::serialized_ruby_strict_local_node
3843
+ end
3844
+
3845
+ #: (Visitor) -> void
3846
+ def accept(visitor)
3847
+ visitor.visit_ruby_strict_local_node(self)
3848
+ end
3849
+
3850
+ #: () -> Array[Herb::AST::Node?]
3851
+ def child_nodes
3852
+ [default_value]
3853
+ end
3854
+
3855
+ #: () -> Array[Herb::AST::Node]
3856
+ def compact_child_nodes
3857
+ child_nodes.compact
3858
+ end
3859
+
3860
+ #: () -> String
3861
+ def inspect
3862
+ tree_inspect.rstrip.gsub(/\s+$/, "")
3863
+ end
3864
+
3865
+ #: (?indent: Integer, ?depth: Integer, ?depth_limit: Integer) -> String
3866
+ def tree_inspect(indent: 0, depth: 0, depth_limit: 10)
3867
+ output = +""
3868
+
3869
+ output += white("@ #{bold(yellow(node_name.to_s))} #{dimmed("(location: #{location.tree_inspect})")}")
3870
+ output += "\n"
3871
+
3872
+ if depth >= depth_limit
3873
+ output += dimmed("└── [depth limit reached ...]\n\n")
3874
+
3875
+ return output.gsub(/^/, " " * indent)
3876
+ end
3877
+
3878
+ output += inspect_errors(prefix: "│ ")
3879
+
3880
+ output += white("├── name: ")
3881
+ output += name ? name.tree_inspect : magenta("∅")
3882
+ output += "\n"
3883
+ output += white("├── default_value: ")
3884
+ if default_value
3885
+ output += "\n"
3886
+ output += "│ └── "
3887
+ output += default_value.tree_inspect(indent: indent, depth: depth + 1, depth_limit: depth_limit).gsub(/^/, " " * (indent + 1)).lstrip.gsub(/^/, "│ ").delete_prefix("│ ")
3888
+ else
3889
+ output += magenta("∅\n")
3890
+ end
3891
+ output += white("├── required: ")
3892
+ output += [true, false].include?(required) ? bold(magenta(required.to_s)) : magenta("∅")
3893
+ output += "\n"
3894
+ output += white("└── double_splat: ")
3895
+ output += [true, false].include?(double_splat) ? bold(magenta(double_splat.to_s)) : magenta("∅")
3896
+ output += "\n"
3897
+ output += "\n"
3898
+
3899
+ output.gsub(/^/, " " * indent)
3900
+ end
3901
+ end
3902
+
3903
+ #: type serialized_erb_strict_locals_node = {
3904
+ #| tag_opening: Herb::Token?,
3905
+ #| content: Herb::Token?,
3906
+ #| tag_closing: Herb::Token?,
3907
+ #| analyzed_ruby: nil,
3908
+ #| prism_node: String?,
3909
+ #| locals: Array[Herb::AST::RubyStrictLocalNode]?,
3910
+ #| }
3911
+ class ERBStrictLocalsNode < Node
3912
+ include Colors
3913
+
3914
+ attr_reader :tag_opening #: Herb::Token?
3915
+ attr_reader :content #: Herb::Token?
3916
+ attr_reader :tag_closing #: Herb::Token?
3917
+ attr_reader :analyzed_ruby #: nil
3918
+ attr_reader :prism_node #: String?
3919
+ attr_reader :locals #: Array[Herb::AST::RubyStrictLocalNode]?
3920
+
3921
+ #: (String, Location, Array[Herb::Errors::Error], Herb::Token, Herb::Token, Herb::Token, nil, String, Array[Herb::AST::RubyStrictLocalNode]) -> void
3922
+ def initialize(type, location, errors, tag_opening, content, tag_closing, analyzed_ruby, prism_node, locals)
3923
+ super(type, location, errors)
3924
+ @tag_opening = tag_opening
3925
+ @content = content
3926
+ @tag_closing = tag_closing
3927
+ @analyzed_ruby = analyzed_ruby
3928
+ @prism_node = prism_node
3929
+ @locals = locals
3930
+ end
3931
+
3932
+ #: () -> Prism::node?
3933
+ def deserialized_prism_node
3934
+ prism_node = @prism_node
3935
+ return nil unless prism_node
3936
+ return nil unless source
3937
+
3938
+ begin
3939
+ require "prism"
3940
+ rescue LoadError
3941
+ warn "The 'prism' gem is required to deserialize Prism nodes. Add it to your Gemfile or install it with: gem install prism"
3942
+ return nil
3943
+ end
3944
+
3945
+ Prism.load(source, prism_node).value
3946
+ end
3947
+
3948
+ #: () -> serialized_erb_strict_locals_node
3949
+ def to_hash
3950
+ super.merge({
3951
+ tag_opening: tag_opening,
3952
+ content: content,
3953
+ tag_closing: tag_closing,
3954
+ analyzed_ruby: analyzed_ruby,
3955
+ prism_node: prism_node,
3956
+ locals: locals,
3957
+ }) #: Herb::serialized_erb_strict_locals_node
3958
+ end
3959
+
3960
+ #: (Visitor) -> void
3961
+ def accept(visitor)
3962
+ visitor.visit_erb_strict_locals_node(self)
3963
+ end
3964
+
3965
+ #: () -> Array[Herb::AST::Node?]
3966
+ def child_nodes
3967
+ [*(locals || [])]
3968
+ end
3969
+
3970
+ #: () -> Array[Herb::AST::Node]
3971
+ def compact_child_nodes
3972
+ child_nodes.compact
3973
+ end
3974
+
3975
+ #: () -> String
3976
+ def inspect
3977
+ tree_inspect.rstrip.gsub(/\s+$/, "")
3978
+ end
3979
+
3980
+ #: (?indent: Integer, ?depth: Integer, ?depth_limit: Integer) -> String
3981
+ def tree_inspect(indent: 0, depth: 0, depth_limit: 10)
3982
+ output = +""
3983
+
3984
+ output += white("@ #{bold(yellow(node_name.to_s))} #{dimmed("(location: #{location.tree_inspect})")}")
3985
+ output += "\n"
3986
+
3987
+ if depth >= depth_limit
3988
+ output += dimmed("└── [depth limit reached ...]\n\n")
3989
+
3990
+ return output.gsub(/^/, " " * indent)
3991
+ end
3992
+
3993
+ output += inspect_errors(prefix: "│ ")
3994
+
3995
+ output += white("├── tag_opening: ")
3996
+ output += tag_opening ? tag_opening.tree_inspect : magenta("∅")
3997
+ output += "\n"
3998
+ output += white("├── content: ")
3999
+ output += content ? content.tree_inspect : magenta("∅")
4000
+ output += "\n"
4001
+ output += white("├── tag_closing: ")
4002
+ output += tag_closing ? tag_closing.tree_inspect : magenta("∅")
4003
+ output += "\n"
4004
+ if prism_node && source
4005
+ output += white("├── prism_node: ")
4006
+ output += Herb::PrismInspect.inspect_prism_serialized(prism_node, source, "│ ")
4007
+ output += "\n"
4008
+ end
4009
+ output += white("└── locals: ")
4010
+ output += inspect_array(locals, prefix: " ", indent: indent, depth: depth + 1, depth_limit: depth_limit)
4011
+ output += "\n"
4012
+
4013
+ output.gsub(/^/, " " * indent)
4014
+ end
4015
+ end
4016
+
3776
4017
  #: type serialized_erb_yield_node = {
3777
4018
  #| tag_opening: Herb::Token?,
3778
4019
  #| content: Herb::Token?,
data/lib/herb/cli.rb CHANGED
@@ -8,7 +8,7 @@ require "optparse"
8
8
  class Herb::CLI
9
9
  include Herb::Colors
10
10
 
11
- attr_accessor :json, :silent, :log_file, :no_timing, :local, :escape, :no_escape, :freeze, :debug, :tool, :strict, :analyze, :track_whitespace, :verbose, :isolate, :arena_stats, :leak_check
11
+ attr_accessor :json, :silent, :log_file, :no_timing, :local, :escape, :no_escape, :freeze, :debug, :tool, :strict, :analyze, :track_whitespace, :verbose, :isolate, :arena_stats, :leak_check, :action_view_helpers, :trim
12
12
 
13
13
  def initialize(args)
14
14
  @args = args
@@ -160,7 +160,7 @@ class Herb::CLI
160
160
  show_config
161
161
  exit(0)
162
162
  when "parse"
163
- Herb.parse(file_content, strict: strict.nil? || strict, analyze: analyze.nil? || analyze, track_whitespace: track_whitespace || false, arena_stats: arena_stats)
163
+ Herb.parse(file_content, strict: strict.nil? || strict, analyze: analyze.nil? || analyze, track_whitespace: track_whitespace || false, arena_stats: arena_stats, action_view_helpers: action_view_helpers || false)
164
164
  when "compile"
165
165
  compile_template
166
166
  when "render"
@@ -298,6 +298,14 @@ class Herb::CLI
298
298
  self.track_whitespace = true
299
299
  end
300
300
 
301
+ parser.on("--action-view-helpers", "Enable Action View helper detection (for parse command) (default: false)") do
302
+ self.action_view_helpers = true
303
+ end
304
+
305
+ parser.on("--trim", "Enable trimming of leading/trailing whitespace (for compile/render commands)") do
306
+ self.trim = true
307
+ end
308
+
301
309
  parser.on("--tool TOOL", "Show config for specific tool: linter, formatter (for config command)") do |t|
302
310
  self.tool = t.to_sym
303
311
  end
@@ -442,6 +450,7 @@ class Herb::CLI
442
450
  options[:debug_filename] = @file if @file
443
451
  end
444
452
 
453
+ options[:trim] = true if trim
445
454
  options[:validate_ruby] = true
446
455
  engine = Herb::Engine.new(file_content, options)
447
456
 
@@ -529,6 +538,7 @@ class Herb::CLI
529
538
  options[:debug_filename] = @file if @file
530
539
  end
531
540
 
541
+ options[:trim] = true if trim
532
542
  engine = Herb::Engine.new(file_content, options)
533
543
  compiled_code = engine.src
534
544