actionview 7.1.2 → 8.0.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -382
  3. data/lib/action_view/base.rb +25 -11
  4. data/lib/action_view/cache_expiry.rb +9 -3
  5. data/lib/action_view/dependency_tracker/erb_tracker.rb +36 -27
  6. data/lib/action_view/dependency_tracker/ruby_tracker.rb +43 -0
  7. data/lib/action_view/dependency_tracker/wildcard_resolver.rb +32 -0
  8. data/lib/action_view/dependency_tracker.rb +2 -1
  9. data/lib/action_view/digestor.rb +6 -2
  10. data/lib/action_view/gem_version.rb +2 -2
  11. data/lib/action_view/helpers/asset_tag_helper.rb +18 -6
  12. data/lib/action_view/helpers/atom_feed_helper.rb +0 -2
  13. data/lib/action_view/helpers/cache_helper.rb +14 -6
  14. data/lib/action_view/helpers/csrf_helper.rb +1 -1
  15. data/lib/action_view/helpers/date_helper.rb +3 -3
  16. data/lib/action_view/helpers/form_helper.rb +282 -273
  17. data/lib/action_view/helpers/form_options_helper.rb +23 -21
  18. data/lib/action_view/helpers/form_tag_helper.rb +104 -69
  19. data/lib/action_view/helpers/number_helper.rb +35 -329
  20. data/lib/action_view/helpers/output_safety_helper.rb +5 -6
  21. data/lib/action_view/helpers/rendering_helper.rb +160 -50
  22. data/lib/action_view/helpers/sanitize_helper.rb +31 -14
  23. data/lib/action_view/helpers/tag_helper.rb +196 -19
  24. data/lib/action_view/helpers/tags/collection_check_boxes.rb +4 -3
  25. data/lib/action_view/helpers/tags/collection_helpers.rb +2 -1
  26. data/lib/action_view/helpers/text_helper.rb +125 -69
  27. data/lib/action_view/helpers/url_helper.rb +6 -80
  28. data/lib/action_view/layouts.rb +11 -13
  29. data/lib/action_view/log_subscriber.rb +8 -4
  30. data/lib/action_view/railtie.rb +0 -1
  31. data/lib/action_view/record_identifier.rb +1 -1
  32. data/lib/action_view/render_parser/prism_render_parser.rb +139 -0
  33. data/lib/action_view/{ripper_ast_parser.rb → render_parser/ripper_render_parser.rb} +162 -10
  34. data/lib/action_view/render_parser.rb +21 -169
  35. data/lib/action_view/renderer/abstract_renderer.rb +1 -1
  36. data/lib/action_view/renderer/partial_renderer.rb +2 -2
  37. data/lib/action_view/renderer/renderer.rb +32 -38
  38. data/lib/action_view/renderer/streaming_template_renderer.rb +0 -1
  39. data/lib/action_view/renderer/template_renderer.rb +3 -3
  40. data/lib/action_view/rendering.rb +6 -7
  41. data/lib/action_view/template/error.rb +11 -0
  42. data/lib/action_view/template/handlers/erb.rb +45 -37
  43. data/lib/action_view/template/renderable.rb +7 -1
  44. data/lib/action_view/template/resolver.rb +0 -3
  45. data/lib/action_view/template.rb +46 -12
  46. data/lib/action_view/test_case.rb +14 -16
  47. data/lib/action_view/unbound_template.rb +4 -4
  48. data/lib/action_view.rb +1 -1
  49. metadata +17 -19
  50. data/lib/action_view/dependency_tracker/ripper_tracker.rb +0 -59
  51. data/lib/assets/compiled/rails-ujs.js +0 -777
@@ -27,10 +27,10 @@ module ActionView
27
27
  extend ActiveSupport::Concern
28
28
  include ActionView::ViewPaths
29
29
 
30
- attr_reader :rendered_format
30
+ attr_internal_reader :rendered_format
31
31
 
32
32
  def initialize
33
- @rendered_format = nil
33
+ @_rendered_format = nil
34
34
  super
35
35
  end
36
36
 
@@ -118,6 +118,7 @@ module ActionView
118
118
 
119
119
  def render_to_body(options = {})
120
120
  _process_options(options)
121
+ _process_render_template_options(options)
121
122
  _render_template(options)
122
123
  end
123
124
 
@@ -136,7 +137,7 @@ module ActionView
136
137
  end
137
138
 
138
139
  rendered_format = rendered_template.format || lookup_context.formats.first
139
- @rendered_format = Template::Types[rendered_format]
140
+ @_rendered_format = Template::Types[rendered_format]
140
141
 
141
142
  rendered_template.body
142
143
  end
@@ -173,18 +174,16 @@ module ActionView
173
174
  end
174
175
 
175
176
  # Normalize options.
176
- def _normalize_options(options)
177
- options = super(options)
177
+ def _process_render_template_options(options)
178
178
  if options[:partial] == true
179
179
  options[:partial] = action_name
180
180
  end
181
181
 
182
- if (options.keys & [:partial, :file, :template]).empty?
182
+ if !options.keys.intersect?([:partial, :file, :template])
183
183
  options[:prefixes] ||= _prefixes
184
184
  end
185
185
 
186
186
  options[:template] ||= (options[:action] || action_name).to_s
187
- options
188
187
  end
189
188
  end
190
189
  end
@@ -27,6 +27,17 @@ module ActionView
27
27
  end
28
28
  end
29
29
 
30
+ class StrictLocalsError < ArgumentError # :nodoc:
31
+ def initialize(argument_error, template)
32
+ message = argument_error.message.
33
+ gsub("unknown keyword:", "unknown local:").
34
+ gsub("missing keyword:", "missing local:").
35
+ gsub("no keywords accepted", "no locals accepted").
36
+ concat(" for #{template.short_identifier}")
37
+ super(message)
38
+ end
39
+ end
40
+
30
41
  class MissingTemplate < ActionViewError # :nodoc:
31
42
  attr_reader :path, :paths, :prefixes, :partial
32
43
 
@@ -42,7 +42,9 @@ module ActionView
42
42
  # source location inside the template.
43
43
  def translate_location(spot, backtrace_location, source)
44
44
  # Tokenize the source line
45
- tokens = ::ERB::Util.tokenize(source.lines[backtrace_location.lineno - 1])
45
+ source_lines = source.lines
46
+ return nil if source_lines.size < backtrace_location.lineno
47
+ tokens = ::ERB::Util.tokenize(source_lines[backtrace_location.lineno - 1])
46
48
  new_first_column = find_offset(spot[:snippet], tokens, spot[:first_column])
47
49
  lineno_delta = spot[:first_lineno] - backtrace_location.lineno
48
50
  spot[:first_lineno] -= lineno_delta
@@ -51,7 +53,7 @@ module ActionView
51
53
  column_delta = spot[:first_column] - new_first_column
52
54
  spot[:first_column] -= column_delta
53
55
  spot[:last_column] -= column_delta
54
- spot[:script_lines] = source.lines
56
+ spot[:script_lines] = source_lines
55
57
 
56
58
  spot
57
59
  rescue NotImplementedError, LocationParsingError
@@ -105,51 +107,57 @@ module ActionView
105
107
  raise WrongEncodingError.new(string, string.encoding)
106
108
  end
107
109
 
110
+ # Find which token in the source template spans the byte range that
111
+ # contains the error_column, then return the offset compared to the
112
+ # original source template.
113
+ #
114
+ # Iterate consecutive pairs of CODE or TEXT tokens, requiring
115
+ # a match of the first token before matching either token.
116
+ #
117
+ # For example, if we want to find tokens A, B, C, we do the following:
118
+ # 1. Find a match for A: test error_column or advance scanner.
119
+ # 2. Find a match for B or A:
120
+ # a. If B: start over with next token set (B, C).
121
+ # b. If A: test error_column or advance scanner.
122
+ # c. Otherwise: Advance 1 byte
123
+ #
124
+ # Prioritize matching the next token over the current token once
125
+ # a match for the current token has been found. This is to prevent
126
+ # the current token from looping past the next token if they both
127
+ # match (i.e. if the current token is a single space character).
108
128
  def find_offset(compiled, source_tokens, error_column)
109
129
  compiled = StringScanner.new(compiled)
130
+ offset_source_tokens(source_tokens).each_cons(2) do |(name, str, offset), (_, next_str, _)|
131
+ matched_str = false
110
132
 
111
- passed_tokens = []
133
+ until compiled.eos?
134
+ if matched_str && next_str && compiled.match?(next_str)
135
+ break
136
+ elsif compiled.match?(str)
137
+ matched_str = true
112
138
 
113
- while tok = source_tokens.shift
114
- tok_name, str = *tok
115
- case tok_name
116
- when :TEXT
117
- loop do
118
- break if compiled.match?(str)
119
- compiled.getch
120
- end
121
- raise LocationParsingError unless compiled.scan(str)
122
- when :CODE
123
- if compiled.pos > error_column
124
- raise LocationParsingError, "We went too far"
125
- end
139
+ if name == :CODE && compiled.pos <= error_column && compiled.pos + str.bytesize >= error_column
140
+ return error_column - compiled.pos + offset
141
+ end
126
142
 
127
- if compiled.pos + str.bytesize >= error_column
128
- offset = error_column - compiled.pos
129
- return passed_tokens.map(&:last).join.bytesize + offset
143
+ compiled.pos += str.bytesize
130
144
  else
131
- unless compiled.scan(str)
132
- raise LocationParsingError, "Couldn't find code snippet"
133
- end
134
- end
135
- when :OPEN
136
- next_tok = source_tokens.first.last
137
- loop do
138
- break if compiled.match?(next_tok)
139
- compiled.getch
145
+ compiled.pos += 1
140
146
  end
141
- when :CLOSE
142
- next_tok = source_tokens.first.last
143
- loop do
144
- break if compiled.match?(next_tok)
145
- compiled.getch
146
- end
147
- else
148
- raise LocationParsingError, "Not implemented: #{tok.first}"
149
147
  end
148
+ end
149
+
150
+ raise LocationParsingError, "Couldn't find code snippet"
151
+ end
150
152
 
151
- passed_tokens << tok
153
+ def offset_source_tokens(source_tokens)
154
+ source_offset = 0
155
+ with_offset = source_tokens.filter_map do |(name, str)|
156
+ result = [name, str, source_offset] if name == :CODE || name == :TEXT
157
+ source_offset += str.bytesize
158
+ result
152
159
  end
160
+ with_offset << [:EOS, nil, source_offset]
153
161
  end
154
162
  end
155
163
  end
@@ -14,10 +14,16 @@ module ActionView
14
14
 
15
15
  def render(context, *args)
16
16
  @renderable.render_in(context)
17
+ rescue NoMethodError
18
+ if !@renderable.respond_to?(:render_in)
19
+ raise ArgumentError, "'#{@renderable.inspect}' is not a renderable object. It must implement #render_in."
20
+ else
21
+ raise
22
+ end
17
23
  end
18
24
 
19
25
  def format
20
- @renderable.format
26
+ @renderable.try(:format)
21
27
  end
22
28
  end
23
29
  end
@@ -4,14 +4,11 @@ require "pathname"
4
4
  require "active_support/core_ext/class"
5
5
  require "active_support/core_ext/module/attribute_accessors"
6
6
  require "action_view/template"
7
- require "thread"
8
7
  require "concurrent/map"
9
8
 
10
9
  module ActionView
11
10
  # = Action View Resolver
12
11
  class Resolver
13
- include ActiveSupport::Deprecation::DeprecatedConstantAccessor
14
-
15
12
  class PathParser # :nodoc:
16
13
  ParsedPath = Struct.new(:path, :details)
17
14
 
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "thread"
4
3
  require "delegate"
5
4
 
6
5
  module ActionView
@@ -148,6 +147,20 @@ module ActionView
148
147
  # <p><%= alert %></p>
149
148
  # <% end %>
150
149
  #
150
+ # By default, templates will accept any <tt>locals</tt> as keyword arguments
151
+ # and make them available to <tt>local_assigns</tt>. To restrict what
152
+ # <tt>local_assigns</tt> a template will accept, add a <tt>locals:</tt> magic comment:
153
+ #
154
+ # <%# locals: (headline:, alerts: []) %>
155
+ #
156
+ # <h1><%= headline %></h1>
157
+ #
158
+ # <% alerts.each do |alert| %>
159
+ # <p><%= alert %></p>
160
+ # <% end %>
161
+ #
162
+ # Read more about strict locals in {Action View Overview}[https://guides.rubyonrails.org/action_view_overview.html#strict-locals]
163
+ # in the guides.
151
164
 
152
165
  eager_autoload do
153
166
  autoload :Error
@@ -216,11 +229,21 @@ module ActionView
216
229
  end
217
230
 
218
231
  def spot(location) # :nodoc:
219
- ast = RubyVM::AbstractSyntaxTree.parse(compiled_source, keep_script_lines: true)
220
232
  node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(location)
221
- node = find_node_by_id(ast, node_id)
233
+ found =
234
+ if RubyVM::InstructionSequence.compile("").to_a[4][:parser] == :prism
235
+ require "prism"
222
236
 
223
- ErrorHighlight.spot(node)
237
+ if Prism::VERSION >= "1.0.0"
238
+ result = Prism.parse(compiled_source).value
239
+ result.breadth_first_search { |node| node.node_id == node_id }
240
+ end
241
+ else
242
+ node = RubyVM::AbstractSyntaxTree.parse(compiled_source, keep_script_lines: true)
243
+ find_node_by_id(node, node_id)
244
+ end
245
+
246
+ ErrorHighlight.spot(found) if found
224
247
  end
225
248
 
226
249
  # Translate an error location returned by ErrorHighlight to the correct
@@ -258,7 +281,8 @@ module ActionView
258
281
  view._run(method_name, self, locals, buffer, add_to_stack: add_to_stack, has_strict_locals: strict_locals?, &block)
259
282
  nil
260
283
  else
261
- view._run(method_name, self, locals, OutputBuffer.new, add_to_stack: add_to_stack, has_strict_locals: strict_locals?, &block)&.to_s
284
+ result = view._run(method_name, self, locals, OutputBuffer.new, add_to_stack: add_to_stack, has_strict_locals: strict_locals?, &block)
285
+ result.is_a?(OutputBuffer) ? result.to_s : result
262
286
  end
263
287
  end
264
288
  rescue => e
@@ -332,7 +356,7 @@ module ActionView
332
356
 
333
357
  # This method is responsible for marking a template as having strict locals
334
358
  # which means the template can only accept the locals defined in a magic
335
- # comment. For example, if your template acceps the locals +title+ and
359
+ # comment. For example, if your template accepts the locals +title+ and
336
360
  # +comment_count+, add the following to your template file:
337
361
  #
338
362
  # <%# locals: (title: "Default title", comment_count: 0) %>
@@ -423,9 +447,13 @@ module ActionView
423
447
 
424
448
  method_arguments =
425
449
  if set_strict_locals
426
- "output_buffer, #{set_strict_locals}"
450
+ if set_strict_locals.include?("&")
451
+ "local_assigns, output_buffer, #{set_strict_locals}"
452
+ else
453
+ "local_assigns, output_buffer, #{set_strict_locals}, &_"
454
+ end
427
455
  else
428
- "local_assigns, output_buffer"
456
+ "local_assigns, output_buffer, &_"
429
457
  end
430
458
 
431
459
  # Make sure that the resulting String to be eval'd is in the
@@ -481,15 +509,18 @@ module ActionView
481
509
 
482
510
  return unless strict_locals?
483
511
 
484
- parameters = mod.instance_method(method_name).parameters - [[:req, :output_buffer]]
512
+ parameters = mod.instance_method(method_name).parameters
513
+ parameters -= [[:req, :local_assigns], [:req, :output_buffer]]
514
+
485
515
  # Check compiled method parameters to ensure that only kwargs
486
516
  # were provided as strict locals, preventing `locals: (foo, *foo)` etc
487
517
  # and allowing `locals: (foo:)`.
488
-
489
518
  non_kwarg_parameters = parameters.select do |parameter|
490
519
  ![:keyreq, :key, :keyrest, :nokey].include?(parameter[0])
491
520
  end
492
521
 
522
+ non_kwarg_parameters.pop if non_kwarg_parameters.last == %i(block _)
523
+
493
524
  unless non_kwarg_parameters.empty?
494
525
  mod.undef_method(method_name)
495
526
 
@@ -501,7 +532,7 @@ module ActionView
501
532
  end
502
533
 
503
534
  unless parameters.any? { |type, _| type == :keyrest }
504
- parameters.map!(&:first)
535
+ parameters.map!(&:last)
505
536
  parameters.sort!
506
537
  @strict_local_keys = parameters.freeze
507
538
  end
@@ -524,12 +555,15 @@ module ActionView
524
555
  end
525
556
  end
526
557
 
558
+ RUBY_RESERVED_KEYWORDS = ::ActiveSupport::Delegation::RUBY_RESERVED_KEYWORDS
559
+ private_constant :RUBY_RESERVED_KEYWORDS
560
+
527
561
  def locals_code
528
562
  return "" if strict_locals?
529
563
 
530
564
  # Only locals with valid variable names get set directly. Others will
531
565
  # still be available in local_assigns.
532
- locals = @locals - Module::RUBY_RESERVED_KEYWORDS
566
+ locals = @locals - RUBY_RESERVED_KEYWORDS
533
567
 
534
568
  locals = locals.grep(/\A(?![A-Z0-9])(?:[[:alnum:]_]|[^\0-\177])+\z/)
535
569
 
@@ -60,7 +60,7 @@ module ActionView
60
60
  include ActiveSupport::Testing::ConstantLookup
61
61
 
62
62
  delegate :lookup_context, to: :controller
63
- attr_accessor :controller, :request, :output_buffer
63
+ attr_accessor :controller, :request, :output_buffer, :rendered
64
64
 
65
65
  module ClassMethods
66
66
  def inherited(descendant) # :nodoc:
@@ -171,10 +171,9 @@ module ActionView
171
171
  # Almost a duplicate from ActionController::Helpers
172
172
  methods.flatten.each do |method|
173
173
  _helpers_for_modification.module_eval <<~end_eval, __FILE__, __LINE__ + 1
174
- def #{method}(*args, &block) # def current_user(*args, &block)
175
- _test_case.send(:'#{method}', *args, &block) # _test_case.send(:'current_user', *args, &block)
176
- end # end
177
- ruby2_keywords(:'#{method}')
174
+ def #{method}(...) # def current_user(...)
175
+ _test_case.send(:'#{method}', ...) # _test_case.send(:'current_user', ...)
176
+ end # end
178
177
  end_eval
179
178
  end
180
179
  end
@@ -198,11 +197,11 @@ module ActionView
198
197
  end
199
198
 
200
199
  included do
201
- class_attribute :content_class, instance_accessor: false, default: Content
200
+ class_attribute :content_class, instance_accessor: false, default: RenderedViewContent
202
201
 
203
202
  setup :setup_with_controller
204
203
 
205
- register_parser :html, -> rendered { Rails::Dom::Testing.html_document.parse(rendered).root }
204
+ register_parser :html, -> rendered { Rails::Dom::Testing.html_document_fragment.parse(rendered) }
206
205
  register_parser :json, -> rendered { JSON.parse(rendered, object_class: ActiveSupport::HashWithIndifferentAccess) }
207
206
 
208
207
  ActiveSupport.run_load_hooks(:action_view_test_case, self)
@@ -224,7 +223,7 @@ module ActionView
224
223
  @request = @controller.request
225
224
  @view_flow = ActionView::OutputFlow.new
226
225
  @output_buffer = ActionView::OutputBuffer.new
227
- @rendered = +""
226
+ @rendered = self.class.content_class.new(+"")
228
227
 
229
228
  test_case_instance = self
230
229
  controller_class.define_method(:_test_case) { test_case_instance }
@@ -244,6 +243,9 @@ module ActionView
244
243
  @_rendered_views ||= RenderedViewsCollection.new
245
244
  end
246
245
 
246
+ ##
247
+ # :method: rendered
248
+ #
247
249
  # Returns the content rendered by the last +render+ call.
248
250
  #
249
251
  # The returned object behaves like a string but also exposes a number of methods
@@ -291,15 +293,12 @@ module ActionView
291
293
  #
292
294
  # assert_pattern { rendered.json => { title: "Hello, world" } }
293
295
  # end
294
- def rendered
295
- @_rendered ||= self.class.content_class.new(@rendered)
296
- end
297
296
 
298
297
  def _routes
299
298
  @controller._routes if @controller.respond_to?(:_routes)
300
299
  end
301
300
 
302
- class Content < SimpleDelegator
301
+ class RenderedViewContent < String # :nodoc:
303
302
  end
304
303
 
305
304
  # Need to experiment if this priority is the best one: rendered => output_buffer
@@ -416,7 +415,7 @@ module ActionView
416
415
  end]
417
416
  end
418
417
 
419
- def method_missing(selector, *args)
418
+ def method_missing(selector, ...)
420
419
  begin
421
420
  routes = @controller.respond_to?(:_routes) && @controller._routes
422
421
  rescue
@@ -426,16 +425,15 @@ module ActionView
426
425
  if routes &&
427
426
  (routes.named_routes.route_defined?(selector) ||
428
427
  routes.mounted_helpers.method_defined?(selector))
429
- @controller.__send__(selector, *args)
428
+ @controller.__send__(selector, ...)
430
429
  else
431
430
  super
432
431
  end
433
432
  end
434
- ruby2_keywords(:method_missing)
435
433
 
436
434
  def respond_to_missing?(name, include_private = false)
437
435
  begin
438
- routes = defined?(@controller) && @controller.respond_to?(:_routes) && @controller._routes
436
+ routes = @controller.respond_to?(:_routes) && @controller._routes
439
437
  rescue
440
438
  # Don't call routes, if there is an error on _routes call
441
439
  end
@@ -26,15 +26,15 @@ module ActionView
26
26
  # while holding the lock.
27
27
  template = (@templates[normalized_locals] ||= build_template(normalized_locals))
28
28
 
29
- # This may have already been assigned, but we've already de-dup'd so
30
- # reassignment is fine.
31
- @templates[locals.dup] = template
32
-
33
29
  if template.strict_locals?
34
30
  # Under strict locals, we only need one template.
35
31
  # This replaces the @templates Concurrent::Map with a hash which
36
32
  # returns this template for every key.
37
33
  @templates = Hash.new(template).freeze
34
+ else
35
+ # This may have already been assigned, but we've already de-dup'd so
36
+ # reassignment is fine.
37
+ @templates[locals.dup] = template
38
38
  end
39
39
  end
40
40
  end
data/lib/action_view.rb CHANGED
@@ -28,7 +28,7 @@ require "active_support/rails"
28
28
  require "action_view/version"
29
29
  require "action_view/deprecator"
30
30
 
31
- # :include: actionview/README.rdoc
31
+ # :include: ../README.rdoc
32
32
  module ActionView
33
33
  extend ActiveSupport::Autoload
34
34
 
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionview
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.2
4
+ version: 8.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-11-10 00:00:00.000000000 Z
10
+ date: 2025-03-12 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activesupport
@@ -16,14 +15,14 @@ dependencies:
16
15
  requirements:
17
16
  - - '='
18
17
  - !ruby/object:Gem::Version
19
- version: 7.1.2
18
+ version: 8.0.2
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - '='
25
24
  - !ruby/object:Gem::Version
26
- version: 7.1.2
25
+ version: 8.0.2
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: builder
29
28
  requirement: !ruby/object:Gem::Requirement
@@ -86,28 +85,28 @@ dependencies:
86
85
  requirements:
87
86
  - - '='
88
87
  - !ruby/object:Gem::Version
89
- version: 7.1.2
88
+ version: 8.0.2
90
89
  type: :development
91
90
  prerelease: false
92
91
  version_requirements: !ruby/object:Gem::Requirement
93
92
  requirements:
94
93
  - - '='
95
94
  - !ruby/object:Gem::Version
96
- version: 7.1.2
95
+ version: 8.0.2
97
96
  - !ruby/object:Gem::Dependency
98
97
  name: activemodel
99
98
  requirement: !ruby/object:Gem::Requirement
100
99
  requirements:
101
100
  - - '='
102
101
  - !ruby/object:Gem::Version
103
- version: 7.1.2
102
+ version: 8.0.2
104
103
  type: :development
105
104
  prerelease: false
106
105
  version_requirements: !ruby/object:Gem::Requirement
107
106
  requirements:
108
107
  - - '='
109
108
  - !ruby/object:Gem::Version
110
- version: 7.1.2
109
+ version: 8.0.2
111
110
  description: Simple, battle-tested conventions and helpers for building web pages.
112
111
  email: david@loudthinking.com
113
112
  executables: []
@@ -126,7 +125,8 @@ files:
126
125
  - lib/action_view/context.rb
127
126
  - lib/action_view/dependency_tracker.rb
128
127
  - lib/action_view/dependency_tracker/erb_tracker.rb
129
- - lib/action_view/dependency_tracker/ripper_tracker.rb
128
+ - lib/action_view/dependency_tracker/ruby_tracker.rb
129
+ - lib/action_view/dependency_tracker/wildcard_resolver.rb
130
130
  - lib/action_view/deprecator.rb
131
131
  - lib/action_view/digestor.rb
132
132
  - lib/action_view/flows.rb
@@ -204,6 +204,8 @@ files:
204
204
  - lib/action_view/railtie.rb
205
205
  - lib/action_view/record_identifier.rb
206
206
  - lib/action_view/render_parser.rb
207
+ - lib/action_view/render_parser/prism_render_parser.rb
208
+ - lib/action_view/render_parser/ripper_render_parser.rb
207
209
  - lib/action_view/renderer/abstract_renderer.rb
208
210
  - lib/action_view/renderer/collection_renderer.rb
209
211
  - lib/action_view/renderer/object_renderer.rb
@@ -213,7 +215,6 @@ files:
213
215
  - lib/action_view/renderer/streaming_template_renderer.rb
214
216
  - lib/action_view/renderer/template_renderer.rb
215
217
  - lib/action_view/rendering.rb
216
- - lib/action_view/ripper_ast_parser.rb
217
218
  - lib/action_view/routing_url_for.rb
218
219
  - lib/action_view/tasks/cache_digests.rake
219
220
  - lib/action_view/template.rb
@@ -240,18 +241,16 @@ files:
240
241
  - lib/action_view/unbound_template.rb
241
242
  - lib/action_view/version.rb
242
243
  - lib/action_view/view_paths.rb
243
- - lib/assets/compiled/rails-ujs.js
244
244
  homepage: https://rubyonrails.org
245
245
  licenses:
246
246
  - MIT
247
247
  metadata:
248
248
  bug_tracker_uri: https://github.com/rails/rails/issues
249
- changelog_uri: https://github.com/rails/rails/blob/v7.1.2/actionview/CHANGELOG.md
250
- documentation_uri: https://api.rubyonrails.org/v7.1.2/
249
+ changelog_uri: https://github.com/rails/rails/blob/v8.0.2/actionview/CHANGELOG.md
250
+ documentation_uri: https://api.rubyonrails.org/v8.0.2/
251
251
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
252
- source_code_uri: https://github.com/rails/rails/tree/v7.1.2/actionview
252
+ source_code_uri: https://github.com/rails/rails/tree/v8.0.2/actionview
253
253
  rubygems_mfa_required: 'true'
254
- post_install_message:
255
254
  rdoc_options: []
256
255
  require_paths:
257
256
  - lib
@@ -259,7 +258,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
259
258
  requirements:
260
259
  - - ">="
261
260
  - !ruby/object:Gem::Version
262
- version: 2.7.0
261
+ version: 3.2.0
263
262
  required_rubygems_version: !ruby/object:Gem::Requirement
264
263
  requirements:
265
264
  - - ">="
@@ -267,8 +266,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
267
266
  version: '0'
268
267
  requirements:
269
268
  - none
270
- rubygems_version: 3.4.18
271
- signing_key:
269
+ rubygems_version: 3.6.2
272
270
  specification_version: 4
273
271
  summary: Rendering framework putting the V in MVC (part of Rails).
274
272
  test_files: []
@@ -1,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActionView
4
- class DependencyTracker # :nodoc:
5
- class RipperTracker # :nodoc:
6
- EXPLICIT_DEPENDENCY = /# Template Dependency: (\S+)/
7
-
8
- def self.call(name, template, view_paths = nil)
9
- new(name, template, view_paths).dependencies
10
- end
11
-
12
- def dependencies
13
- render_dependencies + explicit_dependencies
14
- end
15
-
16
- def self.supports_view_paths? # :nodoc:
17
- true
18
- end
19
-
20
- def initialize(name, template, view_paths = nil)
21
- @name, @template, @view_paths = name, template, view_paths
22
- end
23
-
24
- private
25
- attr_reader :template, :name, :view_paths
26
-
27
- def render_dependencies
28
- return [] unless template.source.include?("render")
29
-
30
- compiled_source = template.handler.call(template, template.source)
31
-
32
- RenderParser.new(@name, compiled_source).render_calls.filter_map do |render_call|
33
- next if render_call.end_with?("/_")
34
- render_call.gsub(%r|/_|, "/")
35
- end
36
- end
37
-
38
- def explicit_dependencies
39
- dependencies = template.source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
40
-
41
- wildcards, explicits = dependencies.partition { |dependency| dependency.end_with?("/*") }
42
-
43
- (explicits + resolve_directories(wildcards)).uniq
44
- end
45
-
46
- def resolve_directories(wildcard_dependencies)
47
- return [] unless view_paths
48
- return [] if wildcard_dependencies.empty?
49
-
50
- # Remove trailing "/*"
51
- prefixes = wildcard_dependencies.map { |query| query[0..-3] }
52
-
53
- view_paths.flat_map(&:all_template_paths).uniq.filter_map { |path|
54
- path.to_s if prefixes.include?(path.prefix)
55
- }.sort
56
- end
57
- end
58
- end
59
- end