herb 0.11.1 → 0.11.2
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/Rakefile +4 -2
- data/config.yml +6 -0
- data/ext/herb/extconf.rb +8 -31
- data/ext/herb/nodes.c +75 -75
- data/ext/herb/parser_options_helpers.c +26 -0
- data/lib/herb/analysis/partial_index.rb +1 -1
- data/lib/herb/analysis/partial_resolution.rb +27 -0
- data/lib/herb/ast/helpers.rb +1 -1
- data/lib/herb/configuration.rb +11 -1
- data/lib/herb/dev/classifier.rb +1 -1
- data/lib/herb/engine/compiler.rb +5 -8
- data/lib/herb/engine/slots/dynamics_compiler.rb +53 -14
- data/lib/herb/engine/slots/subtree_compiler.rb +1 -1
- data/lib/herb/engine/slots/visitor.rb +32 -4
- data/lib/herb/engine/visitors/instrumentation_visitor.rb +18 -6
- data/lib/herb/parser_options.rb +6 -3
- data/lib/herb/project.rb +19 -8
- data/lib/herb/version.rb +1 -1
- data/lib/herb.rb +1 -1
- data/sig/herb/analysis/partial_resolution.rbs +8 -0
- data/sig/herb/configuration.rbs +3 -0
- data/sig/herb/engine/slots/dynamics_compiler.rbs +24 -7
- data/sig/herb/engine/slots/visitor.rbs +14 -0
- data/sig/herb/engine/visitors/instrumentation_visitor.rbs +5 -1
- data/sig/herb/parser_options.rbs +6 -4
- data/sig/herb.rbs +2 -2
- data/src/analyze/action_view/attribute_extraction_helpers.c +40 -21
- data/src/analyze/action_view/generated_handlers.c +36 -36
- data/src/analyze/action_view/image_tag.c +7 -3
- data/src/analyze/action_view/javascript_include_tag.c +6 -3
- data/src/analyze/action_view/link_to.c +23 -23
- data/src/analyze/action_view/registry.c +7 -3
- data/src/analyze/action_view/tag_helper_node_builders.c +6 -13
- data/src/analyze/action_view/tag_helpers.c +139 -90
- data/src/analyze/action_view/turbo_frame_tag.c +5 -4
- data/src/analyze/analyze.c +35 -19
- data/src/analyze/analyze_helpers.c +161 -188
- data/src/analyze/analyzed_ruby.c +8 -7
- data/src/analyze/control_type.c +29 -22
- data/src/analyze/herb_directives.c +16 -20
- data/src/analyze/iteration_nodes.c +69 -24
- data/src/analyze/parse_errors.c +32 -22
- data/src/analyze/postfix_conditionals.c +23 -13
- data/src/analyze/prism_annotate.c +29 -28
- data/src/analyze/render_nodes.c +51 -41
- data/src/analyze/strict_locals.c +14 -15
- data/src/analyze/ternary_conditionals.c +14 -10
- data/src/herb.c +10 -8
- data/src/include/analyze/action_view/tag_helper_handler.h +1 -1
- data/src/include/analyze/action_view/tag_helper_node_builders.h +1 -0
- data/src/include/analyze/action_view/tag_helpers.h +1 -1
- data/src/include/analyze/analyze.h +3 -2
- data/src/include/analyze/analyzed_ruby.h +4 -2
- data/src/include/analyze/helpers.h +6 -6
- data/src/include/herb.h +3 -2
- data/src/include/parser/parser_options.h +5 -0
- data/src/include/prism/prism_context.h +12 -12
- data/src/include/prism/prism_helpers.h +30 -0
- data/src/include/prism_version.h +11 -0
- data/src/include/version.h +1 -1
- data/src/parser/parser_helpers.c +1 -2
- data/src/parser.c +6 -7
- data/src/parser_options_defaults.c +1 -0
- data/src/prism/prism_helpers.c +84 -50
- data/src/prism/ruby_parser.c +20 -20
- data/templates/ext/herb/nodes.c.erb +5 -5
- data/templates/ext/herb/parser_options_helpers.c.erb +33 -0
- data/templates/java/nodes.c.erb +6 -6
- data/templates/java/parser_options_helpers.c.erb +41 -2
- data/templates/java/parser_options_helpers.h.erb +2 -1
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +5 -5
- data/templates/javascript/packages/node/extension/parser_options_helpers.cpp.erb +34 -2
- data/templates/javascript/packages/node/extension/parser_options_helpers.h.erb +1 -1
- data/templates/lib/herb/parser_options.rb.erb +1 -1
- data/templates/rust/src/prism/generated_deserialize.rs.erb +90 -44
- data/templates/rust/src/prism/generated_prettyprint.rs.erb +18 -27
- data/templates/src/analyze/action_view/generated_handlers.c.erb +23 -22
- data/templates/src/include/parser/parser_options.h.erb +10 -0
- data/templates/src/include/prism_version.h.erb +17 -0
- data/templates/src/parser_options_defaults.c.erb +1 -1
- data/templates/template.rb +17 -2
- data/templates/wasm/nodes.cpp.erb +5 -5
- data/templates/wasm/parser_options_helpers.cpp.erb +24 -0
- data/vendor/prism/Rakefile +76 -7
- data/vendor/prism/config.yml +174 -161
- data/vendor/prism/include/prism/arena.h +45 -0
- data/vendor/prism/include/prism/arena.hpp +42 -0
- data/vendor/prism/include/prism/ast.h +2738 -611
- data/vendor/prism/include/prism/ast.hpp +641 -0
- data/vendor/prism/include/prism/buffer.h +60 -0
- data/vendor/prism/include/prism/buffer.hpp +55 -0
- data/vendor/prism/include/prism/comments.h +72 -0
- data/vendor/prism/include/prism/compiler/accel.h +26 -0
- data/vendor/prism/include/prism/compiler/align.h +36 -0
- data/vendor/prism/include/prism/compiler/assume.h +25 -0
- data/vendor/prism/include/prism/compiler/branch.h +26 -0
- data/vendor/prism/include/prism/compiler/bswap.h +46 -0
- data/vendor/prism/include/prism/compiler/cplusplus.hpp +16 -0
- data/vendor/prism/include/prism/compiler/endianness.h +34 -0
- data/vendor/prism/include/prism/compiler/exceptions.hpp +17 -0
- data/vendor/prism/include/prism/compiler/exported.h +24 -0
- data/vendor/prism/include/prism/compiler/fallthrough.h +22 -0
- data/vendor/prism/include/prism/compiler/filesystem.h +32 -0
- data/vendor/prism/include/prism/compiler/flex_array.h +19 -0
- data/vendor/prism/include/prism/compiler/force_inline.h +21 -0
- data/vendor/prism/include/prism/compiler/format.h +27 -0
- data/vendor/prism/include/prism/compiler/inline.h +17 -0
- data/vendor/prism/include/prism/compiler/lifetimebound.hpp +25 -0
- data/vendor/prism/include/prism/compiler/nodiscard.h +22 -0
- data/vendor/prism/include/prism/compiler/nonnull.h +18 -0
- data/vendor/prism/include/prism/compiler/unused.h +18 -0
- data/vendor/prism/include/prism/constant_pool.h +106 -0
- data/vendor/prism/include/prism/diagnostic.h +55 -402
- data/vendor/prism/include/prism/errors_format.h +61 -0
- data/vendor/prism/include/prism/excludes.h +29 -0
- data/vendor/prism/include/prism/integer.h +41 -0
- data/vendor/prism/include/prism/internal/allocator.h +68 -0
- data/vendor/prism/include/prism/internal/allocator_debug.h +88 -0
- data/vendor/prism/include/prism/internal/arena.h +108 -0
- data/vendor/prism/include/prism/internal/bit.h +42 -0
- data/vendor/prism/include/prism/internal/buffer.h +94 -0
- data/vendor/prism/include/prism/internal/char.h +145 -0
- data/vendor/prism/include/prism/internal/comments.h +54 -0
- data/vendor/prism/include/prism/internal/constant_pool.h +152 -0
- data/vendor/prism/include/prism/internal/diagnostic.h +389 -0
- data/vendor/prism/include/prism/{encoding.h → internal/encoding.h} +27 -68
- data/vendor/prism/include/prism/internal/integer.h +68 -0
- data/vendor/prism/include/prism/internal/isinf.h +16 -0
- data/vendor/prism/include/prism/internal/line_offset_list.h +34 -0
- data/vendor/prism/include/prism/{util/pm_list.h → internal/list.h} +11 -52
- data/vendor/prism/include/prism/internal/magic_comments.h +23 -0
- data/vendor/prism/include/prism/internal/memchr.h +15 -0
- data/vendor/prism/include/prism/internal/node.h +42 -0
- data/vendor/prism/include/prism/internal/options.h +232 -0
- data/vendor/prism/include/prism/internal/parser.h +1015 -0
- data/vendor/prism/include/prism/internal/regexp.h +26 -0
- data/vendor/prism/include/prism/internal/serialize.h +39 -0
- data/vendor/prism/include/prism/internal/source.h +72 -0
- data/vendor/prism/include/prism/internal/static_literals.h +60 -0
- data/vendor/prism/include/prism/internal/stringy.h +30 -0
- data/vendor/prism/include/prism/{util/pm_strncasecmp.h → internal/strncasecmp.h} +3 -17
- data/vendor/prism/include/prism/{util/pm_strpbrk.h → internal/strpbrk.h} +7 -20
- data/vendor/prism/include/prism/internal/tokens.h +11 -0
- data/vendor/prism/include/prism/internal/xxh3.h +16 -0
- data/vendor/prism/include/prism/json.h +40 -0
- data/vendor/prism/include/prism/line_offset_list.h +69 -0
- data/vendor/prism/include/prism/magic_comments.h +53 -0
- data/vendor/prism/include/prism/node.h +59 -49
- data/vendor/prism/include/prism/node.hpp +272 -0
- data/vendor/prism/include/prism/node_type.hpp +38 -0
- data/vendor/prism/include/prism/options.h +154 -279
- data/vendor/prism/include/prism/options.hpp +43 -0
- data/vendor/prism/include/prism/parser.h +367 -870
- data/vendor/prism/include/prism/parser.hpp +274 -0
- data/vendor/prism/include/prism/prettyprint.h +14 -9
- data/vendor/prism/include/prism/serialize.h +123 -0
- data/vendor/prism/include/prism/source.h +163 -0
- data/vendor/prism/include/prism/stream.h +36 -0
- data/vendor/prism/include/prism/string_query.h +82 -0
- data/vendor/prism/include/prism/stringy.h +61 -0
- data/vendor/prism/include/prism/stringy.hpp +31 -0
- data/vendor/prism/include/prism/version.h +20 -3
- data/vendor/prism/include/prism.h +35 -320
- data/vendor/prism/include/prism.hpp +24 -0
- data/vendor/prism/src/arena.c +122 -0
- data/vendor/prism/src/{util/pm_buffer.c → buffer.c} +53 -21
- data/vendor/prism/src/{util/pm_char.c → char.c} +28 -57
- data/vendor/prism/src/comments.c +455 -0
- data/vendor/prism/src/constant_pool.c +406 -0
- data/vendor/prism/src/diagnostic.c +120 -68
- data/vendor/prism/src/encoding.c +8 -3
- data/vendor/prism/src/errors_format.c +519 -0
- data/vendor/prism/src/{util/pm_integer.c → integer.c} +38 -22
- data/vendor/prism/src/json.c +5733 -0
- data/vendor/prism/src/line_offset_list.c +100 -0
- data/vendor/prism/src/list.c +24 -0
- data/vendor/prism/src/{util/pm_memchr.c → memchr.c} +8 -6
- data/vendor/prism/src/node.c +3465 -7787
- data/vendor/prism/src/options.c +161 -54
- data/vendor/prism/src/parser.c +371 -0
- data/vendor/prism/src/prettyprint.c +421 -354
- data/vendor/prism/src/prism.c +8522 -7280
- data/vendor/prism/src/regexp.c +960 -45
- data/vendor/prism/src/serialize.c +2434 -2048
- data/vendor/prism/src/source.c +524 -0
- data/vendor/prism/src/static_literals.c +303 -360
- data/vendor/prism/src/string_query.c +180 -0
- data/vendor/prism/src/stringy.c +61 -0
- data/vendor/prism/src/{util/pm_strncasecmp.c → strncasecmp.c} +5 -4
- data/vendor/prism/src/strpbrk.c +447 -0
- data/vendor/prism/src/{token_type.c → tokens.c} +39 -18
- data/vendor/prism/src/xxh3.c +292 -0
- data/vendor/prism/templates/ext/prism/api_node.c.erb +58 -44
- data/vendor/prism/templates/include/prism/ast.h.erb +67 -17
- data/vendor/prism/templates/include/prism/ast.hpp.erb +31 -0
- data/vendor/prism/templates/include/prism/internal/diagnostic.h.erb +60 -0
- data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/AbstractNodeVisitor.java.erb +1 -1
- data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Loader.java.erb +232 -133
- data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Nodes.java.erb +62 -23
- data/vendor/prism/templates/javascript/src/deserialize.js.erb +153 -146
- data/vendor/prism/templates/javascript/src/nodes.js.erb +4 -9
- data/vendor/prism/templates/lib/prism/compiler.rb.erb +14 -5
- data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +20 -12
- data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +37 -11
- data/vendor/prism/templates/lib/prism/dsl.rb.erb +43 -4
- data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +26 -10
- data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +5 -2
- data/vendor/prism/templates/lib/prism/node.rb.erb +283 -105
- data/vendor/prism/templates/lib/prism/reflection.rb.erb +11 -2
- data/vendor/prism/templates/lib/prism/serialize.rb.erb +291 -134
- data/vendor/prism/templates/lib/prism/visitor.rb.erb +18 -0
- data/vendor/prism/templates/src/diagnostic.c.erb +114 -63
- data/vendor/prism/templates/src/json.c.erb +130 -0
- data/vendor/prism/templates/src/node.c.erb +79 -236
- data/vendor/prism/templates/src/prettyprint.c.erb +24 -13
- data/vendor/prism/templates/src/serialize.c.erb +369 -183
- data/vendor/prism/templates/src/{token_type.c.erb → tokens.c.erb} +22 -11
- data/vendor/prism/templates/template.rb +193 -91
- metadata +100 -42
- data/vendor/prism/include/prism/defines.h +0 -260
- data/vendor/prism/include/prism/pack.h +0 -163
- data/vendor/prism/include/prism/regexp.h +0 -43
- data/vendor/prism/include/prism/static_literals.h +0 -121
- data/vendor/prism/include/prism/util/pm_buffer.h +0 -236
- data/vendor/prism/include/prism/util/pm_char.h +0 -204
- data/vendor/prism/include/prism/util/pm_constant_pool.h +0 -218
- data/vendor/prism/include/prism/util/pm_integer.h +0 -130
- data/vendor/prism/include/prism/util/pm_memchr.h +0 -29
- data/vendor/prism/include/prism/util/pm_newline_list.h +0 -113
- data/vendor/prism/include/prism/util/pm_string.h +0 -200
- data/vendor/prism/src/pack.c +0 -509
- data/vendor/prism/src/util/pm_constant_pool.c +0 -342
- data/vendor/prism/src/util/pm_list.c +0 -49
- data/vendor/prism/src/util/pm_newline_list.c +0 -125
- data/vendor/prism/src/util/pm_string.c +0 -381
- data/vendor/prism/src/util/pm_strpbrk.c +0 -206
- data/vendor/prism/templates/include/prism/diagnostic.h.erb +0 -130
- data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +0 -68
- data/vendor/prism/templates/rbi/prism/node.rbi.erb +0 -167
- data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +0 -18
- data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +0 -45
- data/vendor/prism/templates/sig/prism/dsl.rbs.erb +0 -31
- data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +0 -7
- data/vendor/prism/templates/sig/prism/node.rbs.erb +0 -136
- data/vendor/prism/templates/sig/prism/visitor.rbs.erb +0 -17
- data/vendor/prism/templates/sig/prism.rbs.erb +0 -92
|
@@ -71,7 +71,8 @@ module Herb
|
|
|
71
71
|
# An item is keyed by the key its template declares, through `herb-key` or `id` or a
|
|
72
72
|
# `<%# herb:key %>` directive, which is what makes it survive being reordered. `Visitor`
|
|
73
73
|
# decides what that key is and this evaluates it, so an item arrives under the same key the
|
|
74
|
-
# marker around it carries. A collection that declares none falls back to position
|
|
74
|
+
# marker around it carries. A collection that declares none falls back to position, counting
|
|
75
|
+
# from the first iteration, so a change re-renders every row from the first one that differs.
|
|
75
76
|
#
|
|
76
77
|
# ## A partial keeps its own values
|
|
77
78
|
#
|
|
@@ -94,7 +95,7 @@ module Herb
|
|
|
94
95
|
#
|
|
95
96
|
# ## Blocks
|
|
96
97
|
#
|
|
97
|
-
# A tag that takes a block, such as `<%= form_with do |f| %>`, owns an entry holding
|
|
98
|
+
# A tag that takes a block, such as `<%= form_with do |f| %>`, owns an entry holding the markup
|
|
98
99
|
# the block rendered, because the helper wraps that output in markup of its own that only the
|
|
99
100
|
# helper can produce. What the template wrote inside the block keeps its own indices alongside:
|
|
100
101
|
#
|
|
@@ -105,6 +106,20 @@ module Herb
|
|
|
105
106
|
# and the whole block. Slot 1 is inside slot 0, which the client already has to reason about
|
|
106
107
|
# for conditionals and collections.
|
|
107
108
|
#
|
|
109
|
+
# A partial inside a block is the exception to that fallback. It keeps its own values on its slot,
|
|
110
|
+
# and the block's entry is a String that cannot hold them, so the entry leaves the partial's
|
|
111
|
+
# markup out:
|
|
112
|
+
#
|
|
113
|
+
# <%= form_with(model: @user) do |f| %><%= render "card" %><% end %>
|
|
114
|
+
# #=> { 0 => "<form></form>", 1 => { template: "app/views/_card.html.erb", ... } }
|
|
115
|
+
#
|
|
116
|
+
# That entry cannot stand in for the block, so it must not be written over a block holding a
|
|
117
|
+
# partial. The client never writes a block's entry while the page marks slots inside that block.
|
|
118
|
+
# It reports the block as deferred instead, even when nothing in the block changed.
|
|
119
|
+
#
|
|
120
|
+
# A render that comes back as markup, because its template is not compiled for slots, is written
|
|
121
|
+
# into the entry as usual, and the entry stays whole.
|
|
122
|
+
#
|
|
108
123
|
# A block yielding more than once is the exception, since one index cannot stand for the several
|
|
109
124
|
# values its interior took. `each` and the other iterations are compiled as collections for that
|
|
110
125
|
# reason, and a helper that yields repeatedly reports the last value its interior took.
|
|
@@ -117,6 +132,7 @@ module Herb
|
|
|
117
132
|
ITEMS_BUFFER = "__herb_items" #: String
|
|
118
133
|
KEY_BUFFER = "__herb_key" #: String
|
|
119
134
|
OCCURRENCE_BUFFER = "__herb_occurrence" #: String
|
|
135
|
+
RENDERED_BUFFER = "__herb_rendered" #: String
|
|
120
136
|
|
|
121
137
|
BRANCHING_NODES = [
|
|
122
138
|
"AST_ERB_IF_NODE",
|
|
@@ -297,14 +313,15 @@ module Herb
|
|
|
297
313
|
|
|
298
314
|
return super if erb_escaped?(opening)
|
|
299
315
|
|
|
300
|
-
|
|
316
|
+
rendering = node.is_a?(Herb::AST::ERBRenderNode)
|
|
317
|
+
should_escape = !rendering && should_escape_output?(opening)
|
|
301
318
|
index = claim(node)
|
|
302
319
|
|
|
303
320
|
@tokens << [
|
|
304
321
|
should_escape ? :expr_block_escaped : :expr_block,
|
|
305
322
|
node.content.value.strip,
|
|
306
323
|
current_context,
|
|
307
|
-
index
|
|
324
|
+
[index, rendering]
|
|
308
325
|
]
|
|
309
326
|
|
|
310
327
|
@last_trim_consumed_newline = false
|
|
@@ -335,7 +352,9 @@ module Herb
|
|
|
335
352
|
|
|
336
353
|
@engine.send(:add_dynamic, value, context, index, escaped, nested: nested)
|
|
337
354
|
when :expr_block, :expr_block_escaped
|
|
338
|
-
|
|
355
|
+
index, rendering = extra
|
|
356
|
+
|
|
357
|
+
@engine.send(:add_dynamic_block, value, index, type == :expr_block_escaped, rendering: rendering)
|
|
339
358
|
when :expr_block_end
|
|
340
359
|
@engine.send(:add_expression_block_end, value, escaped: extra)
|
|
341
360
|
end
|
|
@@ -461,7 +480,7 @@ module Herb
|
|
|
461
480
|
|
|
462
481
|
#: (Integer) -> String?
|
|
463
482
|
def item_key(index)
|
|
464
|
-
@slot_visitor.slots[index]&.
|
|
483
|
+
@slot_visitor.slots[index]&.item_key
|
|
465
484
|
end
|
|
466
485
|
|
|
467
486
|
#: (untyped, Symbol) -> void
|
|
@@ -541,6 +560,7 @@ module Herb
|
|
|
541
560
|
#: (String, ?Hash[Symbol, untyped]) -> void
|
|
542
561
|
def initialize(input, properties = {})
|
|
543
562
|
@block_depth = 0
|
|
563
|
+
@nested_renders = [] #: Array[[Integer?]?]
|
|
544
564
|
@scopes = [] #: Array[Integer]
|
|
545
565
|
@withheld = {} #: Hash[Integer, bool]
|
|
546
566
|
@input = input
|
|
@@ -599,6 +619,8 @@ module Herb
|
|
|
599
619
|
return add_block_dynamic("(#{assignment(index, value)}).fetch(-1)")
|
|
600
620
|
end
|
|
601
621
|
|
|
622
|
+
return add_block_render(index ? assignment(index, value) : value) if nested
|
|
623
|
+
|
|
602
624
|
return add_block_dynamic(index ? assignment(index, value) : value)
|
|
603
625
|
end
|
|
604
626
|
return if index.nil?
|
|
@@ -611,19 +633,24 @@ module Herb
|
|
|
611
633
|
@slot_visitor.slots[index]&.type == :boolean_attribute
|
|
612
634
|
end
|
|
613
635
|
|
|
614
|
-
#: (String, Integer?, bool) -> void
|
|
615
|
-
def add_dynamic_block(code, index, escaped)
|
|
636
|
+
#: (String, Integer?, bool, ?rendering: bool) -> void
|
|
637
|
+
def add_dynamic_block(code, index, escaped, rendering: false)
|
|
616
638
|
@_in_expression_block = true
|
|
617
639
|
@_expression_block_open_paren = true
|
|
618
640
|
|
|
619
641
|
opening = escaped ? "#{@escapefunc}((" : "("
|
|
642
|
+
nested_render = rendering && !@block_depth.zero?
|
|
620
643
|
|
|
621
644
|
@src << if @block_depth.zero?
|
|
622
645
|
"; #{current_scope}[#{index}] = #{opening}#{code}"
|
|
646
|
+
elsif nested_render
|
|
647
|
+
"; #{RENDERED_BUFFER} = #{opening}#{code}"
|
|
623
648
|
else
|
|
624
649
|
"; #{@bufvar} << #{opening}#{code}"
|
|
625
650
|
end
|
|
626
651
|
|
|
652
|
+
@nested_renders.push(nested_render ? [index] : nil)
|
|
653
|
+
|
|
627
654
|
open_block
|
|
628
655
|
end
|
|
629
656
|
|
|
@@ -634,6 +661,14 @@ module Herb
|
|
|
634
661
|
close_block
|
|
635
662
|
|
|
636
663
|
super
|
|
664
|
+
|
|
665
|
+
nested_render = @nested_renders.pop
|
|
666
|
+
|
|
667
|
+
return unless nested_render
|
|
668
|
+
|
|
669
|
+
index = nested_render.first
|
|
670
|
+
|
|
671
|
+
add_block_render(index ? assignment(index, RENDERED_BUFFER) : RENDERED_BUFFER)
|
|
637
672
|
end
|
|
638
673
|
|
|
639
674
|
#: () -> String
|
|
@@ -738,6 +773,10 @@ module Herb
|
|
|
738
773
|
#: (Integer) -> void
|
|
739
774
|
def scope_open_collection(index)
|
|
740
775
|
@src << "; #{ITEMS_BUFFER}#{index} = ::Hash.new;"
|
|
776
|
+
|
|
777
|
+
slot = @slot_visitor.slots[index]
|
|
778
|
+
|
|
779
|
+
@src << "; #{slot.position_variable} = -1;" if slot&.positional?
|
|
741
780
|
end
|
|
742
781
|
|
|
743
782
|
#: (Integer, ?String?) -> void
|
|
@@ -752,17 +791,12 @@ module Herb
|
|
|
752
791
|
def scope_item_end(index)
|
|
753
792
|
leave_scope(index)
|
|
754
793
|
|
|
755
|
-
return unless
|
|
794
|
+
return unless @slot_visitor.slots[index]&.item_key
|
|
756
795
|
|
|
757
796
|
@src << item_seeds(index)
|
|
758
797
|
@src << "; #{ITEMS_BUFFER}#{index}[#{KEY_BUFFER}#{index}.to_s] = #{SCOPE_BUFFER}#{index};"
|
|
759
798
|
end
|
|
760
799
|
|
|
761
|
-
#: (Integer) -> bool
|
|
762
|
-
def keyed?(index)
|
|
763
|
-
!@slot_visitor.slots[index]&.key_expression.nil?
|
|
764
|
-
end
|
|
765
|
-
|
|
766
800
|
#: (Integer) -> String
|
|
767
801
|
def item_seeds(index)
|
|
768
802
|
names = @slot_visitor.seeded_item_states[index]
|
|
@@ -826,6 +860,11 @@ module Herb
|
|
|
826
860
|
@slot_visitor.slots[index]&.interpolated? || false
|
|
827
861
|
end
|
|
828
862
|
|
|
863
|
+
#: (String) -> void
|
|
864
|
+
def add_block_render(value)
|
|
865
|
+
add_block_dynamic("::Hash === (#{RENDERED_BUFFER} = (#{value})) ? \"\" : #{RENDERED_BUFFER}.to_s")
|
|
866
|
+
end
|
|
867
|
+
|
|
829
868
|
#: (String) -> void
|
|
830
869
|
def add_block_dynamic(value)
|
|
831
870
|
@src << "; " << @bufvar << " << (" << value << ");"
|
|
@@ -66,6 +66,7 @@ module Herb
|
|
|
66
66
|
COVERED = "@_herb_covered" #: String
|
|
67
67
|
OCCURRENCES = "@_herb_region_occurrences" #: String
|
|
68
68
|
OCCURRENCE = "_herb_occurrence" #: String
|
|
69
|
+
POSITION = "__herb_position" #: String
|
|
69
70
|
NAME_ATTRIBUTE = "data-herb-name" #: String
|
|
70
71
|
KEY_ATTRIBUTE = "herb-key" #: String
|
|
71
72
|
|
|
@@ -109,6 +110,15 @@ module Herb
|
|
|
109
110
|
|
|
110
111
|
#: () -> bool
|
|
111
112
|
def interpolated? = Types.interpolated?(type)
|
|
113
|
+
|
|
114
|
+
#: () -> bool
|
|
115
|
+
def positional? = type == :collection && key_expression.nil?
|
|
116
|
+
|
|
117
|
+
#: () -> String
|
|
118
|
+
def position_variable = "#{POSITION}#{index}"
|
|
119
|
+
|
|
120
|
+
#: () -> String?
|
|
121
|
+
def item_key = positional? ? "#{position_variable} += 1" : key_expression
|
|
112
122
|
end
|
|
113
123
|
|
|
114
124
|
#: (String) -> bool
|
|
@@ -1886,6 +1896,8 @@ module Herb
|
|
|
1886
1896
|
wrap_items(child, slot_index, namespace)
|
|
1887
1897
|
mark_branches(child, slot_index, namespace)
|
|
1888
1898
|
|
|
1899
|
+
index += insert_position_counter(array, index, slot_index)
|
|
1900
|
+
|
|
1889
1901
|
if slot_index && slot_index != anchored
|
|
1890
1902
|
if @slots[slot_index].type == :keyed
|
|
1891
1903
|
park_keyed(slot_index, child, namespace)
|
|
@@ -2072,12 +2084,23 @@ module Herb
|
|
|
2072
2084
|
bodies
|
|
2073
2085
|
end
|
|
2074
2086
|
|
|
2087
|
+
#: (Array[untyped], Integer, Integer?) -> Integer
|
|
2088
|
+
def insert_position_counter(array, index, slot_index)
|
|
2089
|
+
slot = slot_index ? @slots[slot_index] : nil
|
|
2090
|
+
|
|
2091
|
+
return 0 unless slot&.positional?
|
|
2092
|
+
|
|
2093
|
+
array.insert(index, erb_code_node("#{slot.position_variable} = -1"))
|
|
2094
|
+
|
|
2095
|
+
1
|
|
2096
|
+
end
|
|
2097
|
+
|
|
2075
2098
|
#: (Herb::AST::Node, Integer?, ?Symbol) -> void
|
|
2076
2099
|
def wrap_items(node, slot_index, namespace = :html)
|
|
2077
2100
|
return unless slot_index
|
|
2078
2101
|
|
|
2079
2102
|
slot = @slots[slot_index]
|
|
2080
|
-
return unless slot.type == :collection
|
|
2103
|
+
return unless slot.type == :collection
|
|
2081
2104
|
|
|
2082
2105
|
BRANCH_BODY_PROPERTIES.each do |property|
|
|
2083
2106
|
next unless node.respond_to?(property)
|
|
@@ -2090,13 +2113,18 @@ module Herb
|
|
|
2090
2113
|
|
|
2091
2114
|
body.unshift(
|
|
2092
2115
|
text_node(@markers.item_open_prefix(slot_index)),
|
|
2093
|
-
erb_code_node("#{@bufvar} << ::Herb::Engine.raw((#{slot.
|
|
2094
|
-
text_node(@markers.item_open_suffix)
|
|
2116
|
+
erb_code_node("#{@bufvar} << ::Herb::Engine.raw((#{slot.item_key}).to_s)"),
|
|
2117
|
+
text_node(@markers.item_open_suffix),
|
|
2118
|
+
erb_code_node("begin")
|
|
2095
2119
|
)
|
|
2096
2120
|
|
|
2097
2121
|
body.insert(3, erb_code_node(%(#{COVERED}[#{covered_key(key).inspect}] = true))) if parked && client?
|
|
2098
2122
|
|
|
2099
|
-
body.push(
|
|
2123
|
+
body.push(
|
|
2124
|
+
erb_code_node("ensure"),
|
|
2125
|
+
text_node(@markers.item_close(slot_index)),
|
|
2126
|
+
erb_code_node("end")
|
|
2127
|
+
)
|
|
2100
2128
|
end
|
|
2101
2129
|
end
|
|
2102
2130
|
|
|
@@ -140,6 +140,8 @@ module Herb
|
|
|
140
140
|
|
|
141
141
|
instrument(node)
|
|
142
142
|
|
|
143
|
+
return [node] if literal?(node)
|
|
144
|
+
|
|
143
145
|
if framed?(node)
|
|
144
146
|
[enter_node(node), node, leave_node(node)]
|
|
145
147
|
elsif erb_outputs?(node)
|
|
@@ -158,6 +160,12 @@ module Herb
|
|
|
158
160
|
replacement
|
|
159
161
|
end
|
|
160
162
|
|
|
163
|
+
def literal?(node)
|
|
164
|
+
return false unless node.respond_to?(:tag_opening) && node.tag_opening
|
|
165
|
+
|
|
166
|
+
erb_escaped?(node.tag_opening.value)
|
|
167
|
+
end
|
|
168
|
+
|
|
161
169
|
def framed?(node)
|
|
162
170
|
return true if node.is_a?(Herb::AST::ERBRenderNode)
|
|
163
171
|
|
|
@@ -197,9 +205,9 @@ module Herb
|
|
|
197
205
|
body = code(node)
|
|
198
206
|
call = captured?(node) ? "output" : "at"
|
|
199
207
|
|
|
200
|
-
return
|
|
208
|
+
return rewrapped(node, "#{SESSION}.#{call}(#{position(node)}) {\n#{body}\n}") if spans_lines?(body)
|
|
201
209
|
|
|
202
|
-
|
|
210
|
+
rewrapped(node, "#{SESSION}.#{call}(#{position(node)}) { #{body} }")
|
|
203
211
|
end
|
|
204
212
|
|
|
205
213
|
def captured?(node)
|
|
@@ -221,10 +229,10 @@ module Herb
|
|
|
221
229
|
body = code(node)
|
|
222
230
|
|
|
223
231
|
if spans_lines?(body)
|
|
224
|
-
return
|
|
232
|
+
return rewrapped(node, "#{SESSION}.enter(#{position(node)}); begin\n#{body}\nensure; #{SESSION}.leave; end")
|
|
225
233
|
end
|
|
226
234
|
|
|
227
|
-
|
|
235
|
+
rewrapped(node, "#{SESSION}.enter(#{position(node)}); begin; #{body}; ensure; #{SESSION}.leave; end")
|
|
228
236
|
end
|
|
229
237
|
|
|
230
238
|
#: (String) -> bool
|
|
@@ -276,11 +284,15 @@ module Herb
|
|
|
276
284
|
node.content&.value.to_s.strip
|
|
277
285
|
end
|
|
278
286
|
|
|
279
|
-
def
|
|
287
|
+
def rewrapped(node, code)
|
|
288
|
+
erb_node(node, node.tag_opening.value, code, closing: node.tag_closing&.value || "%>")
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def erb_node(node, opening, code, closing: "%>")
|
|
280
292
|
Herb::AST::ERBContentNode.build(
|
|
281
293
|
tag_opening: Herb::Token.from("TOKEN_ERB_START", opening),
|
|
282
294
|
content: Herb::Token.from("TOKEN_ERB_CONTENT", " #{code} "),
|
|
283
|
-
tag_closing: Herb::Token.from("TOKEN_ERB_END",
|
|
295
|
+
tag_closing: Herb::Token.from("TOKEN_ERB_END", closing),
|
|
284
296
|
valid: true,
|
|
285
297
|
location: node.location
|
|
286
298
|
)
|
data/lib/herb/parser_options.rb
CHANGED
|
@@ -19,6 +19,7 @@ module Herb
|
|
|
19
19
|
attr_reader :prism_nodes_deep #: bool
|
|
20
20
|
attr_reader :prism_program #: bool
|
|
21
21
|
attr_reader :render_nodes #: bool
|
|
22
|
+
attr_reader :ruby_version #: String?
|
|
22
23
|
attr_reader :strict #: bool
|
|
23
24
|
attr_reader :strict_locals #: bool
|
|
24
25
|
attr_reader :timeout #: Numeric
|
|
@@ -45,8 +46,8 @@ module Herb
|
|
|
45
46
|
DEFAULT_TRACK_WHITESPACE = false #: bool
|
|
46
47
|
DEFAULT_TRANSFORM_CONDITIONALS = false #: bool
|
|
47
48
|
|
|
48
|
-
#: (?action_view_helpers: bool, ?analyze: bool, ?arena_stats: bool, ?dot_notation_tags: bool, ?erb_openers: Array[String], ?herb_directives: bool, ?html: bool, ?iteration_nodes: bool, ?max_errors: Integer?, ?prism_nodes: bool, ?prism_nodes_deep: bool, ?prism_program: bool, ?render_nodes: bool, ?strict: bool, ?strict_locals: bool, ?timeout: Numeric, ?track_locations: bool, ?track_whitespace: bool, ?transform_conditionals: bool) -> void
|
|
49
|
-
def initialize(action_view_helpers: DEFAULT_ACTION_VIEW_HELPERS, analyze: DEFAULT_ANALYZE, arena_stats: DEFAULT_CAPTURE_ARENA_STATS, dot_notation_tags: DEFAULT_DOT_NOTATION_TAGS, erb_openers: [], herb_directives: DEFAULT_HERB_DIRECTIVES, html: DEFAULT_HTML, iteration_nodes: DEFAULT_ITERATION_NODES, max_errors: DEFAULT_MAX_ERRORS, prism_nodes: DEFAULT_PRISM_NODES, prism_nodes_deep: DEFAULT_PRISM_NODES_DEEP, prism_program: DEFAULT_PRISM_PROGRAM, render_nodes: DEFAULT_RENDER_NODES, strict: DEFAULT_STRICT, strict_locals: DEFAULT_STRICT_LOCALS, timeout: DEFAULT_TIMEOUT, track_locations: DEFAULT_TRACK_LOCATIONS, track_whitespace: DEFAULT_TRACK_WHITESPACE, transform_conditionals: DEFAULT_TRANSFORM_CONDITIONALS)
|
|
49
|
+
#: (?action_view_helpers: bool, ?analyze: bool, ?arena_stats: bool, ?dot_notation_tags: bool, ?erb_openers: Array[String], ?herb_directives: bool, ?html: bool, ?iteration_nodes: bool, ?max_errors: Integer?, ?prism_nodes: bool, ?prism_nodes_deep: bool, ?prism_program: bool, ?render_nodes: bool, ?ruby_version: String?, ?strict: bool, ?strict_locals: bool, ?timeout: Numeric, ?track_locations: bool, ?track_whitespace: bool, ?transform_conditionals: bool) -> void
|
|
50
|
+
def initialize(action_view_helpers: DEFAULT_ACTION_VIEW_HELPERS, analyze: DEFAULT_ANALYZE, arena_stats: DEFAULT_CAPTURE_ARENA_STATS, dot_notation_tags: DEFAULT_DOT_NOTATION_TAGS, erb_openers: [], herb_directives: DEFAULT_HERB_DIRECTIVES, html: DEFAULT_HTML, iteration_nodes: DEFAULT_ITERATION_NODES, max_errors: DEFAULT_MAX_ERRORS, prism_nodes: DEFAULT_PRISM_NODES, prism_nodes_deep: DEFAULT_PRISM_NODES_DEEP, prism_program: DEFAULT_PRISM_PROGRAM, render_nodes: DEFAULT_RENDER_NODES, ruby_version: "4.0", strict: DEFAULT_STRICT, strict_locals: DEFAULT_STRICT_LOCALS, timeout: DEFAULT_TIMEOUT, track_locations: DEFAULT_TRACK_LOCATIONS, track_whitespace: DEFAULT_TRACK_WHITESPACE, transform_conditionals: DEFAULT_TRANSFORM_CONDITIONALS)
|
|
50
51
|
@action_view_helpers = action_view_helpers
|
|
51
52
|
@analyze = analyze
|
|
52
53
|
@arena_stats = arena_stats
|
|
@@ -60,6 +61,7 @@ module Herb
|
|
|
60
61
|
@prism_nodes_deep = prism_nodes_deep
|
|
61
62
|
@prism_program = prism_program
|
|
62
63
|
@render_nodes = render_nodes
|
|
64
|
+
@ruby_version = ruby_version
|
|
63
65
|
@strict = strict
|
|
64
66
|
@strict_locals = strict_locals
|
|
65
67
|
@timeout = timeout
|
|
@@ -68,7 +70,7 @@ module Herb
|
|
|
68
70
|
@transform_conditionals = transform_conditionals
|
|
69
71
|
end
|
|
70
72
|
|
|
71
|
-
#: () -> Hash[Symbol, (bool | Numeric | Array[String] | nil)]
|
|
73
|
+
#: () -> Hash[Symbol, (bool | Numeric | String | Array[String] | nil)]
|
|
72
74
|
def to_h
|
|
73
75
|
{
|
|
74
76
|
action_view_helpers: @action_view_helpers,
|
|
@@ -84,6 +86,7 @@ module Herb
|
|
|
84
86
|
prism_nodes_deep: @prism_nodes_deep,
|
|
85
87
|
prism_program: @prism_program,
|
|
86
88
|
render_nodes: @render_nodes,
|
|
89
|
+
ruby_version: @ruby_version,
|
|
87
90
|
strict: @strict,
|
|
88
91
|
strict_locals: @strict_locals,
|
|
89
92
|
timeout: @timeout,
|
data/lib/herb/project.rb
CHANGED
|
@@ -332,7 +332,7 @@ module Herb
|
|
|
332
332
|
return unless issue_type[:key] == :invalid_ruby && file_content
|
|
333
333
|
|
|
334
334
|
begin
|
|
335
|
-
engine = Herb::Engine.new(file_content, filename: file_path, escape: true, visitors: [])
|
|
335
|
+
engine = Herb::Engine.new(file_content, filename: file_path, escape: true, parser_options: engine_parser_options, visitors: [])
|
|
336
336
|
puts ""
|
|
337
337
|
puts "**Compiled Ruby:**"
|
|
338
338
|
puts "```ruby"
|
|
@@ -345,6 +345,16 @@ module Herb
|
|
|
345
345
|
|
|
346
346
|
private
|
|
347
347
|
|
|
348
|
+
#: () -> Hash[Symbol, untyped]
|
|
349
|
+
def parser_options
|
|
350
|
+
@parser_options ||= configuration.parser_options
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
#: () -> Hash[Symbol, untyped]
|
|
354
|
+
def engine_parser_options
|
|
355
|
+
@engine_parser_options ||= configuration.engine_option("parser_options", {}).transform_keys(&:to_sym).merge(parser_options)
|
|
356
|
+
end
|
|
357
|
+
|
|
348
358
|
def process_file(file_path)
|
|
349
359
|
isolate ? process_file_isolated(file_path) : process_file_direct(file_path)
|
|
350
360
|
end
|
|
@@ -362,7 +372,7 @@ module Herb
|
|
|
362
372
|
end
|
|
363
373
|
|
|
364
374
|
Timeout.timeout(file_timeout) do
|
|
365
|
-
parse_result = Herb.parse(file_content)
|
|
375
|
+
parse_result = Herb.parse(file_content, **parser_options)
|
|
366
376
|
|
|
367
377
|
if parse_result.failed?
|
|
368
378
|
result[:file_content] = file_content
|
|
@@ -401,7 +411,7 @@ module Herb
|
|
|
401
411
|
$stderr.reopen(stderr_file.path, "w")
|
|
402
412
|
|
|
403
413
|
begin
|
|
404
|
-
parse_result = Herb.parse(file_content)
|
|
414
|
+
parse_result = Herb.parse(file_content, **parser_options)
|
|
405
415
|
exit!(parse_result.failed? ? 2 : 0)
|
|
406
416
|
rescue StandardError => e
|
|
407
417
|
warn "Ruby exception: #{e.class}: #{e.message}"
|
|
@@ -457,7 +467,7 @@ module Herb
|
|
|
457
467
|
end
|
|
458
468
|
|
|
459
469
|
def classify_parse_errors(file_path, file_content)
|
|
460
|
-
default_result = Herb.parse(file_content)
|
|
470
|
+
default_result = Herb.parse(file_content, **parser_options)
|
|
461
471
|
|
|
462
472
|
diagnostics = if default_result.respond_to?(:errors) && default_result.errors.any?
|
|
463
473
|
default_result.errors.map do |error|
|
|
@@ -470,8 +480,8 @@ module Herb
|
|
|
470
480
|
end
|
|
471
481
|
end
|
|
472
482
|
|
|
473
|
-
no_strict_result = Herb.parse(file_content, strict: false)
|
|
474
|
-
no_analyze_result = Herb.parse(file_content, analyze: false)
|
|
483
|
+
no_strict_result = Herb.parse(file_content, **parser_options, strict: false)
|
|
484
|
+
no_analyze_result = Herb.parse(file_content, **parser_options, analyze: false)
|
|
475
485
|
|
|
476
486
|
if no_strict_result.success?
|
|
477
487
|
{ status: :strict_parse_error, diagnostics: diagnostics,
|
|
@@ -496,6 +506,7 @@ module Herb
|
|
|
496
506
|
file_content,
|
|
497
507
|
filename: file_path,
|
|
498
508
|
escape: true,
|
|
509
|
+
parser_options: engine_parser_options,
|
|
499
510
|
validate_ruby: validate_ruby,
|
|
500
511
|
visitors: Herb::Engine::Validators.all
|
|
501
512
|
)
|
|
@@ -514,7 +525,7 @@ module Herb
|
|
|
514
525
|
|
|
515
526
|
# Retry without validators
|
|
516
527
|
begin
|
|
517
|
-
Herb::Engine.new(file_content, filename: file_path, escape: true, visitors: [], validate_ruby: validate_ruby)
|
|
528
|
+
Herb::Engine.new(file_content, filename: file_path, escape: true, parser_options: engine_parser_options, visitors: [], validate_ruby: validate_ruby)
|
|
518
529
|
error_name = e.is_a?(Herb::Engine::SecurityError) ? "SecurityError" : "ValidationError"
|
|
519
530
|
return { status: :validation_error, file_content: file_content,
|
|
520
531
|
compilation_error: compilation_error,
|
|
@@ -526,7 +537,7 @@ module Herb
|
|
|
526
537
|
|
|
527
538
|
# Retry without strict mode
|
|
528
539
|
begin
|
|
529
|
-
Herb::Engine.new(file_content, filename: file_path, escape: true, strict: false, validate_ruby: validate_ruby)
|
|
540
|
+
Herb::Engine.new(file_content, filename: file_path, escape: true, parser_options: engine_parser_options, strict: false, validate_ruby: validate_ruby)
|
|
530
541
|
return { status: :strict_compilation_failed, file_content: file_content,
|
|
531
542
|
compilation_error: compilation_error,
|
|
532
543
|
diagnostics: [{ name: "CompilationError", message: "#{e.message} (strict mode)" }],
|
data/lib/herb/version.rb
CHANGED
data/lib/herb.rb
CHANGED
|
@@ -67,7 +67,7 @@ rescue LoadError => e
|
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
module Herb
|
|
70
|
-
#: (String input, ?track_whitespace: bool, ?track_locations: bool, ?analyze: bool, ?strict: bool, ?action_view_helpers: bool, ?transform_conditionals: bool, ?dot_notation_tags: bool, ?render_nodes: bool, ?strict_locals: bool, ?herb_directives: bool, ?iteration_nodes: bool, ?prism_nodes: bool, ?prism_nodes_deep: bool, ?prism_program: bool, ?html: bool, ?erb_openers: Array[String], ?arena_stats: bool) -> ParseResult
|
|
70
|
+
#: (String input, ?track_whitespace: bool, ?track_locations: bool, ?analyze: bool, ?strict: bool, ?action_view_helpers: bool, ?transform_conditionals: bool, ?dot_notation_tags: bool, ?render_nodes: bool, ?strict_locals: bool, ?herb_directives: bool, ?iteration_nodes: bool, ?prism_nodes: bool, ?prism_nodes_deep: bool, ?prism_program: bool, ?html: bool, ?erb_openers: Array[String], ?ruby_version: String?, ?arena_stats: bool) -> ParseResult
|
|
71
71
|
def self.parse(...)
|
|
72
72
|
Backend.parse(...)
|
|
73
73
|
end
|
|
@@ -5,6 +5,8 @@ module Herb
|
|
|
5
5
|
module PartialResolution
|
|
6
6
|
PARTIAL_PREFIX: String
|
|
7
7
|
|
|
8
|
+
VARIANT_SEPARATOR: String
|
|
9
|
+
|
|
8
10
|
EXTENSIONS: Array[String]
|
|
9
11
|
|
|
10
12
|
EXTENSION_ALTERNATIVES: String
|
|
@@ -41,6 +43,12 @@ module Herb
|
|
|
41
43
|
# : (Array[String]) -> Array[String]
|
|
42
44
|
def self.by_precedence: (Array[String]) -> Array[String]
|
|
43
45
|
|
|
46
|
+
# : (String?) -> String?
|
|
47
|
+
def self.template_variant: (String?) -> String?
|
|
48
|
+
|
|
49
|
+
# : (Array[String], String?) -> String?
|
|
50
|
+
def self.preferred_for: (Array[String], String?) -> String?
|
|
51
|
+
|
|
44
52
|
# : (String, String | Pathname) -> String?
|
|
45
53
|
def self.template_name_for: (String, String | Pathname) -> String?
|
|
46
54
|
|
data/sig/herb/configuration.rbs
CHANGED
|
@@ -65,7 +65,8 @@ module Herb
|
|
|
65
65
|
# An item is keyed by the key its template declares, through `herb-key` or `id` or a
|
|
66
66
|
# `<%# herb:key %>` directive, which is what makes it survive being reordered. `Visitor`
|
|
67
67
|
# decides what that key is and this evaluates it, so an item arrives under the same key the
|
|
68
|
-
# marker around it carries. A collection that declares none falls back to position
|
|
68
|
+
# marker around it carries. A collection that declares none falls back to position, counting
|
|
69
|
+
# from the first iteration, so a change re-renders every row from the first one that differs.
|
|
69
70
|
#
|
|
70
71
|
# ## A partial keeps its own values
|
|
71
72
|
#
|
|
@@ -88,7 +89,7 @@ module Herb
|
|
|
88
89
|
#
|
|
89
90
|
# ## Blocks
|
|
90
91
|
#
|
|
91
|
-
# A tag that takes a block, such as `<%= form_with do |f| %>`, owns an entry holding
|
|
92
|
+
# A tag that takes a block, such as `<%= form_with do |f| %>`, owns an entry holding the markup
|
|
92
93
|
# the block rendered, because the helper wraps that output in markup of its own that only the
|
|
93
94
|
# helper can produce. What the template wrote inside the block keeps its own indices alongside:
|
|
94
95
|
#
|
|
@@ -99,6 +100,20 @@ module Herb
|
|
|
99
100
|
# and the whole block. Slot 1 is inside slot 0, which the client already has to reason about
|
|
100
101
|
# for conditionals and collections.
|
|
101
102
|
#
|
|
103
|
+
# A partial inside a block is the exception to that fallback. It keeps its own values on its slot,
|
|
104
|
+
# and the block's entry is a String that cannot hold them, so the entry leaves the partial's
|
|
105
|
+
# markup out:
|
|
106
|
+
#
|
|
107
|
+
# <%= form_with(model: @user) do |f| %><%= render "card" %><% end %>
|
|
108
|
+
# #=> { 0 => "<form></form>", 1 => { template: "app/views/_card.html.erb", ... } }
|
|
109
|
+
#
|
|
110
|
+
# That entry cannot stand in for the block, so it must not be written over a block holding a
|
|
111
|
+
# partial. The client never writes a block's entry while the page marks slots inside that block.
|
|
112
|
+
# It reports the block as deferred instead, even when nothing in the block changed.
|
|
113
|
+
#
|
|
114
|
+
# A render that comes back as markup, because its template is not compiled for slots, is written
|
|
115
|
+
# into the entry as usual, and the entry stays whole.
|
|
116
|
+
#
|
|
102
117
|
# A block yielding more than once is the exception, since one index cannot stand for the several
|
|
103
118
|
# values its interior took. `each` and the other iterations are compiled as collections for that
|
|
104
119
|
# reason, and a helper that yields repeatedly reports the last value its interior took.
|
|
@@ -117,6 +132,8 @@ module Herb
|
|
|
117
132
|
|
|
118
133
|
OCCURRENCE_BUFFER: String
|
|
119
134
|
|
|
135
|
+
RENDERED_BUFFER: String
|
|
136
|
+
|
|
120
137
|
BRANCHING_NODES: Array[String]
|
|
121
138
|
|
|
122
139
|
class Compiler < Herb::Engine::Compiler
|
|
@@ -249,8 +266,8 @@ module Herb
|
|
|
249
266
|
# : (Integer) -> bool
|
|
250
267
|
def boolean_presence?: (Integer) -> bool
|
|
251
268
|
|
|
252
|
-
# : (String, Integer?, bool) -> void
|
|
253
|
-
def add_dynamic_block: (String, Integer?, bool) -> void
|
|
269
|
+
# : (String, Integer?, bool, ?rendering: bool) -> void
|
|
270
|
+
def add_dynamic_block: (String, Integer?, bool, ?rendering: bool) -> void
|
|
254
271
|
|
|
255
272
|
# : (String, ?escaped: bool) -> void
|
|
256
273
|
def add_expression_block_end: (String, ?escaped: bool) -> void
|
|
@@ -305,9 +322,6 @@ module Herb
|
|
|
305
322
|
# : (Integer) -> void
|
|
306
323
|
def scope_item_end: (Integer) -> void
|
|
307
324
|
|
|
308
|
-
# : (Integer) -> bool
|
|
309
|
-
def keyed?: (Integer) -> bool
|
|
310
|
-
|
|
311
325
|
# : (Integer) -> String
|
|
312
326
|
def item_seeds: (Integer) -> String
|
|
313
327
|
|
|
@@ -332,6 +346,9 @@ module Herb
|
|
|
332
346
|
# : (Integer) -> bool
|
|
333
347
|
def interpolated?: (Integer) -> bool
|
|
334
348
|
|
|
349
|
+
# : (String) -> void
|
|
350
|
+
def add_block_render: (String) -> void
|
|
351
|
+
|
|
335
352
|
# : (String) -> void
|
|
336
353
|
def add_block_dynamic: (String) -> void
|
|
337
354
|
|
|
@@ -57,6 +57,8 @@ module Herb
|
|
|
57
57
|
|
|
58
58
|
OCCURRENCE: String
|
|
59
59
|
|
|
60
|
+
POSITION: String
|
|
61
|
+
|
|
60
62
|
NAME_ATTRIBUTE: String
|
|
61
63
|
|
|
62
64
|
KEY_ATTRIBUTE: String
|
|
@@ -121,6 +123,15 @@ module Herb
|
|
|
121
123
|
|
|
122
124
|
# : () -> bool
|
|
123
125
|
def interpolated?: () -> bool
|
|
126
|
+
|
|
127
|
+
# : () -> bool
|
|
128
|
+
def positional?: () -> bool
|
|
129
|
+
|
|
130
|
+
# : () -> String
|
|
131
|
+
def position_variable: () -> String
|
|
132
|
+
|
|
133
|
+
# : () -> String?
|
|
134
|
+
def item_key: () -> String?
|
|
124
135
|
end
|
|
125
136
|
|
|
126
137
|
# : (String) -> bool
|
|
@@ -562,6 +573,9 @@ module Herb
|
|
|
562
573
|
# : (untyped) -> Array[Array[Herb::AST::Node]]
|
|
563
574
|
def branch_bodies: (untyped) -> Array[Array[Herb::AST::Node]]
|
|
564
575
|
|
|
576
|
+
# : (Array[untyped], Integer, Integer?) -> Integer
|
|
577
|
+
def insert_position_counter: (Array[untyped], Integer, Integer?) -> Integer
|
|
578
|
+
|
|
565
579
|
# : (Herb::AST::Node, Integer?, ?Symbol) -> void
|
|
566
580
|
def wrap_items: (Herb::AST::Node, Integer?, ?Symbol) -> void
|
|
567
581
|
|
|
@@ -72,6 +72,8 @@ module Herb
|
|
|
72
72
|
# : (Herb::AST::Node, Herb::AST::Node) -> Herb::AST::Node
|
|
73
73
|
def replacing: (Herb::AST::Node, Herb::AST::Node) -> Herb::AST::Node
|
|
74
74
|
|
|
75
|
+
def literal?: (untyped node) -> untyped
|
|
76
|
+
|
|
75
77
|
def framed?: (untyped node) -> untyped
|
|
76
78
|
|
|
77
79
|
def assignment?: (untyped node) -> untyped
|
|
@@ -105,7 +107,9 @@ module Herb
|
|
|
105
107
|
|
|
106
108
|
def code: (untyped node) -> untyped
|
|
107
109
|
|
|
108
|
-
def
|
|
110
|
+
def rewrapped: (untyped node, untyped code) -> untyped
|
|
111
|
+
|
|
112
|
+
def erb_node: (untyped node, untyped opening, untyped code, ?closing: untyped) -> untyped
|
|
109
113
|
end
|
|
110
114
|
end
|
|
111
115
|
end
|