actionview 6.0.6.1 → 6.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionview might be problematic. Click here for more details.

Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +152 -325
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/action_view/base.rb +20 -51
  6. data/lib/action_view/cache_expiry.rb +1 -2
  7. data/lib/action_view/context.rb +0 -1
  8. data/lib/action_view/dependency_tracker.rb +10 -4
  9. data/lib/action_view/digestor.rb +3 -2
  10. data/lib/action_view/gem_version.rb +3 -3
  11. data/lib/action_view/helpers/asset_tag_helper.rb +40 -15
  12. data/lib/action_view/helpers/asset_url_helper.rb +6 -4
  13. data/lib/action_view/helpers/atom_feed_helper.rb +2 -1
  14. data/lib/action_view/helpers/cache_helper.rb +10 -16
  15. data/lib/action_view/helpers/date_helper.rb +4 -4
  16. data/lib/action_view/helpers/form_helper.rb +59 -17
  17. data/lib/action_view/helpers/form_options_helper.rb +7 -16
  18. data/lib/action_view/helpers/form_tag_helper.rb +8 -6
  19. data/lib/action_view/helpers/javascript_helper.rb +3 -3
  20. data/lib/action_view/helpers/number_helper.rb +6 -6
  21. data/lib/action_view/helpers/rendering_helper.rb +11 -3
  22. data/lib/action_view/helpers/sanitize_helper.rb +2 -2
  23. data/lib/action_view/helpers/tag_helper.rb +96 -52
  24. data/lib/action_view/helpers/tags/base.rb +9 -5
  25. data/lib/action_view/helpers/tags/date_field.rb +1 -1
  26. data/lib/action_view/helpers/tags/date_select.rb +2 -2
  27. data/lib/action_view/helpers/tags/datetime_local_field.rb +1 -1
  28. data/lib/action_view/helpers/tags/label.rb +4 -0
  29. data/lib/action_view/helpers/tags/month_field.rb +1 -1
  30. data/lib/action_view/helpers/tags/select.rb +1 -1
  31. data/lib/action_view/helpers/tags/time_field.rb +1 -1
  32. data/lib/action_view/helpers/tags/week_field.rb +1 -1
  33. data/lib/action_view/helpers/text_helper.rb +1 -1
  34. data/lib/action_view/helpers/translation_helper.rb +88 -53
  35. data/lib/action_view/helpers/url_helper.rb +107 -13
  36. data/lib/action_view/layouts.rb +3 -2
  37. data/lib/action_view/log_subscriber.rb +26 -10
  38. data/lib/action_view/lookup_context.rb +3 -18
  39. data/lib/action_view/path_set.rb +0 -3
  40. data/lib/action_view/railtie.rb +35 -46
  41. data/lib/action_view/renderer/abstract_renderer.rb +93 -14
  42. data/lib/action_view/renderer/collection_renderer.rb +192 -0
  43. data/lib/action_view/renderer/object_renderer.rb +34 -0
  44. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +25 -26
  45. data/lib/action_view/renderer/partial_renderer.rb +20 -282
  46. data/lib/action_view/renderer/renderer.rb +44 -1
  47. data/lib/action_view/renderer/streaming_template_renderer.rb +5 -1
  48. data/lib/action_view/renderer/template_renderer.rb +15 -12
  49. data/lib/action_view/rendering.rb +3 -1
  50. data/lib/action_view/routing_url_for.rb +1 -1
  51. data/lib/action_view/template/handlers/erb/erubi.rb +9 -7
  52. data/lib/action_view/template/handlers/erb.rb +10 -14
  53. data/lib/action_view/template/handlers.rb +0 -26
  54. data/lib/action_view/template/html.rb +1 -11
  55. data/lib/action_view/template/raw_file.rb +0 -3
  56. data/lib/action_view/template/renderable.rb +24 -0
  57. data/lib/action_view/template/resolver.rb +82 -40
  58. data/lib/action_view/template/text.rb +0 -3
  59. data/lib/action_view/template.rb +9 -49
  60. data/lib/action_view/test_case.rb +18 -25
  61. data/lib/action_view/testing/resolvers.rb +10 -31
  62. data/lib/action_view/unbound_template.rb +3 -3
  63. data/lib/action_view/view_paths.rb +34 -36
  64. data/lib/action_view.rb +4 -1
  65. data/lib/assets/compiled/rails-ujs.js +1 -1
  66. metadata +20 -18
@@ -1,36 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "concurrent/map"
4
3
  require "action_view/renderer/partial_renderer/collection_caching"
5
4
 
6
5
  module ActionView
7
- class PartialIteration
8
- # The number of iterations that will be done by the partial.
9
- attr_reader :size
10
-
11
- # The current iteration of the partial.
12
- attr_reader :index
13
-
14
- def initialize(size)
15
- @size = size
16
- @index = 0
17
- end
18
-
19
- # Check if this is the first iteration of the partial.
20
- def first?
21
- index == 0
22
- end
23
-
24
- # Check if this is the last iteration of the partial.
25
- def last?
26
- index == size - 1
27
- end
28
-
29
- def iterate! # :nodoc:
30
- @index += 1
31
- end
32
- end
33
-
34
6
  # = Action View Partials
35
7
  #
36
8
  # There's also a convenience method for rendering sub templates within the current controller that depends on a
@@ -282,281 +254,47 @@ module ActionView
282
254
  class PartialRenderer < AbstractRenderer
283
255
  include CollectionCaching
284
256
 
285
- PREFIXED_PARTIAL_NAMES = Concurrent::Map.new do |h, k|
286
- h[k] = Concurrent::Map.new
257
+ def initialize(lookup_context, options)
258
+ super(lookup_context)
259
+ @options = options
260
+ @locals = @options[:locals] || {}
261
+ @details = extract_details(@options)
287
262
  end
288
263
 
289
- def initialize(*)
290
- super
291
- @context_prefix = @lookup_context.prefixes.first
292
- end
264
+ def render(partial, context, block)
265
+ template = find_template(partial, template_keys(partial))
293
266
 
294
- def render(context, options, block)
295
- as = as_variable(options)
296
- setup(context, options, as, block)
297
-
298
- if @path
299
- if @has_object || @collection
300
- @variable, @variable_counter, @variable_iteration = retrieve_variable(@path, as)
301
- @template_keys = retrieve_template_keys(@variable)
302
- else
303
- @template_keys = @locals.keys
304
- end
305
- template = find_partial(@path, @template_keys)
306
- @variable ||= template.variable
307
- else
308
- if options[:cached]
309
- raise NotImplementedError, "render caching requires a template. Please specify a partial when rendering"
310
- end
311
- template = nil
267
+ if !block && (layout = @options[:layout])
268
+ layout = find_template(layout.to_s, template_keys(partial))
312
269
  end
313
270
 
314
- if @collection
315
- render_collection(context, template)
316
- else
317
- render_partial(context, template)
318
- end
271
+ render_partial_template(context, @locals, template, layout, block)
319
272
  end
320
273
 
321
274
  private
322
- def render_collection(view, template)
323
- identifier = (template && template.identifier) || @path
324
- instrument(:collection, identifier: identifier, count: @collection.size) do |payload|
325
- return RenderedCollection.empty(@lookup_context.formats.first) if @collection.blank?
326
-
327
- spacer = if @options.key?(:spacer_template)
328
- spacer_template = find_template(@options[:spacer_template], @locals.keys)
329
- build_rendered_template(spacer_template.render(view, @locals), spacer_template)
330
- else
331
- RenderedTemplate::EMPTY_SPACER
332
- end
333
-
334
- collection_body = if template
335
- cache_collection_render(payload, view, template) do
336
- collection_with_template(view, template)
337
- end
338
- else
339
- collection_without_template(view)
340
- end
341
- build_rendered_collection(collection_body, spacer)
342
- end
275
+ def template_keys(_)
276
+ @locals.keys
343
277
  end
344
278
 
345
- def render_partial(view, template)
346
- instrument(:partial, identifier: template.identifier) do |payload|
347
- locals, block = @locals, @block
348
- object, as = @object, @variable
349
-
350
- if !block && (layout = @options[:layout])
351
- layout = find_template(layout.to_s, @template_keys)
352
- end
353
-
354
- object = locals[as] if object.nil? # Respect object when object is false
355
- locals[as] = object if @has_object
356
-
357
- content = template.render(view, locals) do |*name|
279
+ def render_partial_template(view, locals, template, layout, block)
280
+ ActiveSupport::Notifications.instrument(
281
+ "render_partial.action_view",
282
+ identifier: template.identifier,
283
+ layout: layout && layout.virtual_path
284
+ ) do |payload|
285
+ content = template.render(view, locals, add_to_stack: !block) do |*name|
358
286
  view._layout_for(*name, &block)
359
287
  end
360
288
 
361
289
  content = layout.render(view, locals) { content } if layout
362
290
  payload[:cache_hit] = view.view_renderer.cache_hits[template.virtual_path]
363
- build_rendered_template(content, template, layout)
364
- end
365
- end
366
-
367
- # Sets up instance variables needed for rendering a partial. This method
368
- # finds the options and details and extracts them. The method also contains
369
- # logic that handles the type of object passed in as the partial.
370
- #
371
- # If +options[:partial]+ is a string, then the <tt>@path</tt> instance variable is
372
- # set to that string. Otherwise, the +options[:partial]+ object must
373
- # respond to +to_partial_path+ in order to setup the path.
374
- def setup(context, options, as, block)
375
- @options = options
376
- @block = block
377
-
378
- @locals = options[:locals] || {}
379
- @details = extract_details(options)
380
-
381
- partial = options[:partial]
382
-
383
- if String === partial
384
- @has_object = options.key?(:object)
385
- @object = options[:object]
386
- @collection = collection_from_options
387
- @path = partial
388
- else
389
- @has_object = true
390
- @object = partial
391
- @collection = collection_from_object || collection_from_options
392
-
393
- if @collection
394
- paths = @collection_data = @collection.map { |o| partial_path(o, context) }
395
- if paths.uniq.length == 1
396
- @path = paths.first
397
- else
398
- paths.map! { |path| retrieve_variable(path, as).unshift(path) }
399
- @path = nil
400
- end
401
- else
402
- @path = partial_path(@object, context)
403
- end
404
- end
405
-
406
- self
407
- end
408
-
409
- def as_variable(options)
410
- if as = options[:as]
411
- raise_invalid_option_as(as) unless /\A[a-z_]\w*\z/.match?(as.to_s)
412
- as.to_sym
413
- end
414
- end
415
-
416
- def collection_from_options
417
- if @options.key?(:collection)
418
- collection = @options[:collection]
419
- collection ? collection.to_a : []
291
+ build_rendered_template(content, template)
420
292
  end
421
293
  end
422
294
 
423
- def collection_from_object
424
- @object.to_ary if @object.respond_to?(:to_ary)
425
- end
426
-
427
- def find_partial(path, template_keys)
428
- find_template(path, template_keys)
429
- end
430
-
431
295
  def find_template(path, locals)
432
296
  prefixes = path.include?(?/) ? [] : @lookup_context.prefixes
433
297
  @lookup_context.find_template(path, prefixes, true, locals, @details)
434
298
  end
435
-
436
- def collection_with_template(view, template)
437
- locals = @locals
438
- as, counter, iteration = @variable, @variable_counter, @variable_iteration
439
-
440
- if layout = @options[:layout]
441
- layout = find_template(layout, @template_keys)
442
- end
443
-
444
- partial_iteration = PartialIteration.new(@collection.size)
445
- locals[iteration] = partial_iteration
446
-
447
- @collection.map do |object|
448
- locals[as] = object
449
- locals[counter] = partial_iteration.index
450
-
451
- content = template.render(view, locals)
452
- content = layout.render(view, locals) { content } if layout
453
- partial_iteration.iterate!
454
- build_rendered_template(content, template, layout)
455
- end
456
- end
457
-
458
- def collection_without_template(view)
459
- locals, collection_data = @locals, @collection_data
460
- cache = {}
461
- keys = @locals.keys
462
-
463
- partial_iteration = PartialIteration.new(@collection.size)
464
-
465
- @collection.map do |object|
466
- index = partial_iteration.index
467
- path, as, counter, iteration = collection_data[index]
468
-
469
- locals[as] = object
470
- locals[counter] = index
471
- locals[iteration] = partial_iteration
472
-
473
- template = (cache[path] ||= find_template(path, keys + [as, counter, iteration]))
474
- content = template.render(view, locals)
475
- partial_iteration.iterate!
476
- build_rendered_template(content, template)
477
- end
478
- end
479
-
480
- # Obtains the path to where the object's partial is located. If the object
481
- # responds to +to_partial_path+, then +to_partial_path+ will be called and
482
- # will provide the path. If the object does not respond to +to_partial_path+,
483
- # then an +ArgumentError+ is raised.
484
- #
485
- # If +prefix_partial_path_with_controller_namespace+ is true, then this
486
- # method will prefix the partial paths with a namespace.
487
- def partial_path(object, view)
488
- object = object.to_model if object.respond_to?(:to_model)
489
-
490
- path = if object.respond_to?(:to_partial_path)
491
- object.to_partial_path
492
- else
493
- raise ArgumentError.new("'#{object.inspect}' is not an ActiveModel-compatible object. It must implement :to_partial_path.")
494
- end
495
-
496
- if view.prefix_partial_path_with_controller_namespace
497
- prefixed_partial_names[path] ||= merge_prefix_into_object_path(@context_prefix, path.dup)
498
- else
499
- path
500
- end
501
- end
502
-
503
- def prefixed_partial_names
504
- @prefixed_partial_names ||= PREFIXED_PARTIAL_NAMES[@context_prefix]
505
- end
506
-
507
- def merge_prefix_into_object_path(prefix, object_path)
508
- if prefix.include?(?/) && object_path.include?(?/)
509
- prefixes = []
510
- prefix_array = File.dirname(prefix).split("/")
511
- object_path_array = object_path.split("/")[0..-3] # skip model dir & partial
512
-
513
- prefix_array.each_with_index do |dir, index|
514
- break if dir == object_path_array[index]
515
- prefixes << dir
516
- end
517
-
518
- (prefixes << object_path).join("/")
519
- else
520
- object_path
521
- end
522
- end
523
-
524
- def retrieve_template_keys(variable)
525
- keys = @locals.keys
526
- keys << variable
527
- if @collection
528
- keys << @variable_counter
529
- keys << @variable_iteration
530
- end
531
- keys
532
- end
533
-
534
- def retrieve_variable(path, as)
535
- variable = as || begin
536
- base = path[-1] == "/" ? "" : File.basename(path)
537
- raise_invalid_identifier(path) unless base =~ /\A_?(.*?)(?:\.\w+)*\z/
538
- $1.to_sym
539
- end
540
- if @collection
541
- variable_counter = :"#{variable}_counter"
542
- variable_iteration = :"#{variable}_iteration"
543
- end
544
- [variable, variable_counter, variable_iteration]
545
- end
546
-
547
- IDENTIFIER_ERROR_MESSAGE = "The partial name (%s) is not a valid Ruby identifier; " \
548
- "make sure your partial name starts with underscore."
549
-
550
- OPTION_AS_ERROR_MESSAGE = "The value (%s) of the option `as` is not a valid Ruby identifier; " \
551
- "make sure it starts with lowercase letter, " \
552
- "and is followed by any combination of letters, numbers and underscores."
553
-
554
- def raise_invalid_identifier(path)
555
- raise ArgumentError.new(IDENTIFIER_ERROR_MESSAGE % (path))
556
- end
557
-
558
- def raise_invalid_option_as(as)
559
- raise ArgumentError.new(OPTION_AS_ERROR_MESSAGE % (as))
560
- end
561
299
  end
562
300
  end
@@ -62,7 +62,50 @@ module ActionView
62
62
  end
63
63
 
64
64
  def render_partial_to_object(context, options, &block) #:nodoc:
65
- PartialRenderer.new(@lookup_context).render(context, options, block)
65
+ partial = options[:partial]
66
+ if String === partial
67
+ collection = collection_from_options(options)
68
+
69
+ if collection
70
+ # Collection + Partial
71
+ renderer = CollectionRenderer.new(@lookup_context, options)
72
+ renderer.render_collection_with_partial(collection, partial, context, block)
73
+ else
74
+ if options.key?(:object)
75
+ # Object + Partial
76
+ renderer = ObjectRenderer.new(@lookup_context, options)
77
+ renderer.render_object_with_partial(options[:object], partial, context, block)
78
+ else
79
+ # Partial
80
+ renderer = PartialRenderer.new(@lookup_context, options)
81
+ renderer.render(partial, context, block)
82
+ end
83
+ end
84
+ else
85
+ collection = collection_from_object(partial) || collection_from_options(options)
86
+
87
+ if collection
88
+ # Collection + Derived Partial
89
+ renderer = CollectionRenderer.new(@lookup_context, options)
90
+ renderer.render_collection_derive_partial(collection, context, block)
91
+ else
92
+ # Object + Derived Partial
93
+ renderer = ObjectRenderer.new(@lookup_context, options)
94
+ renderer.render_object_derive_partial(partial, context, block)
95
+ end
96
+ end
66
97
  end
98
+
99
+ private
100
+ def collection_from_options(options)
101
+ if options.key?(:collection)
102
+ collection = options[:collection]
103
+ collection || []
104
+ end
105
+ end
106
+
107
+ def collection_from_object(object)
108
+ object if object.respond_to?(:to_ary)
109
+ end
67
110
  end
68
111
  end
@@ -62,7 +62,11 @@ module ActionView
62
62
  output = ActionView::StreamingBuffer.new(buffer)
63
63
  yielder = lambda { |*name| view._layout_for(*name) }
64
64
 
65
- instrument(:template, identifier: template.identifier, layout: layout.try(:virtual_path)) do
65
+ ActiveSupport::Notifications.instrument(
66
+ "render_template.action_view",
67
+ identifier: template.identifier,
68
+ layout: layout && layout.virtual_path
69
+ ) do
66
70
  outer_config = I18n.config
67
71
  fiber = Fiber.new do
68
72
  I18n.config = outer_config
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/object/try"
4
-
5
3
  module ActionView
6
4
  class TemplateRenderer < AbstractRenderer #:nodoc:
7
5
  def render(context, options)
@@ -28,8 +26,7 @@ module ActionView
28
26
  if File.exist?(options[:file])
29
27
  Template::RawFile.new(options[:file])
30
28
  else
31
- ActiveSupport::Deprecation.warn "render file: should be given the absolute path to a file"
32
- @lookup_context.with_fallbacks.find_template(options[:file], nil, false, keys, @details)
29
+ raise ArgumentError, "`render file:` should be given the absolute path to a file. '#{options[:file]}' was given instead"
33
30
  end
34
31
  elsif options.key?(:inline)
35
32
  handler = Template.handler_for_extension(options[:type] || "erb")
@@ -39,6 +36,8 @@ module ActionView
39
36
  @lookup_context.formats.first
40
37
  end
41
38
  Template::Inline.new(options[:inline], "inline template", handler, locals: keys, format: format)
39
+ elsif options.key?(:renderable)
40
+ Template::Renderable.new(options[:renderable])
42
41
  elsif options.key?(:template)
43
42
  if options[:template].respond_to?(:render)
44
43
  options[:template]
@@ -54,7 +53,11 @@ module ActionView
54
53
  # supplied as well.
55
54
  def render_template(view, template, layout_name, locals)
56
55
  render_with_layout(view, template, layout_name, locals) do |layout|
57
- instrument(:template, identifier: template.identifier, layout: layout.try(:virtual_path)) do
56
+ ActiveSupport::Notifications.instrument(
57
+ "render_template.action_view",
58
+ identifier: template.identifier,
59
+ layout: layout && layout.virtual_path
60
+ ) do
58
61
  template.render(view, locals) { |*name| view._layout_for(*name) }
59
62
  end
60
63
  end
@@ -62,15 +65,16 @@ module ActionView
62
65
 
63
66
  def render_with_layout(view, template, path, locals)
64
67
  layout = path && find_layout(path, locals.keys, [formats.first])
65
- content = yield(layout)
66
68
 
67
69
  body = if layout
68
- view.view_flow.set(:layout, content)
69
- layout.render(view, locals) { |*name| view._layout_for(*name) }
70
+ ActiveSupport::Notifications.instrument("render_layout.action_view", identifier: layout.identifier) do
71
+ view.view_flow.set(:layout, yield(layout))
72
+ layout.render(view, locals) { |*name| view._layout_for(*name) }
73
+ end
70
74
  else
71
- content
75
+ yield
72
76
  end
73
- build_rendered_template(body, template, layout)
77
+ build_rendered_template(body, template)
74
78
  end
75
79
 
76
80
  # This is the method which actually finds the layout using details in the lookup
@@ -88,8 +92,7 @@ module ActionView
88
92
  when String
89
93
  begin
90
94
  if layout.start_with?("/")
91
- ActiveSupport::Deprecation.warn "Rendering layouts from an absolute path is deprecated."
92
- @lookup_context.with_fallbacks.find_template(layout, nil, false, [], details)
95
+ raise ArgumentError, "Rendering layouts from an absolute path is not supported."
93
96
  else
94
97
  @lookup_context.find_template(layout, nil, false, [], details)
95
98
  end
@@ -33,7 +33,7 @@ module ActionView
33
33
  super
34
34
  end
35
35
 
36
- # Overwrite process to setup I18n proxy.
36
+ # Overwrite process to set up I18n proxy.
37
37
  def process(*) #:nodoc:
38
38
  old_config, I18n.config = I18n.config, I18nProxy.new(I18n.config, lookup_context)
39
39
  super
@@ -144,6 +144,8 @@ module ActionView
144
144
  else
145
145
  if action.respond_to?(:permitted?) && action.permitted?
146
146
  options = action
147
+ elsif action.respond_to?(:render_in)
148
+ options[:renderable] = action
147
149
  else
148
150
  options[:partial] = action
149
151
  end
@@ -105,7 +105,7 @@ module ActionView
105
105
  end
106
106
  else
107
107
  method = _generate_paths_by_default ? :path : :url
108
- builder = ActionDispatch::Routing::PolymorphicRoutes::HelperMethodBuilder.send(method)
108
+ builder = ActionDispatch::Routing::PolymorphicRoutes::HelperMethodBuilder.public_send(method)
109
109
 
110
110
  case options
111
111
  when Symbol
@@ -13,9 +13,11 @@ module ActionView
13
13
 
14
14
  # Dup properties so that we don't modify argument
15
15
  properties = Hash[properties]
16
- properties[:preamble] = ""
17
- properties[:postamble] = "@output_buffer.to_s"
18
- properties[:bufvar] = "@output_buffer"
16
+
17
+ properties[:bufvar] ||= "@output_buffer"
18
+ properties[:preamble] ||= ""
19
+ properties[:postamble] ||= "#{properties[:bufvar]}.to_s"
20
+
19
21
  properties[:escapefunc] = ""
20
22
 
21
23
  super
@@ -37,7 +39,7 @@ module ActionView
37
39
  if text == "\n"
38
40
  @newline_pending += 1
39
41
  else
40
- src << "@output_buffer.safe_append='"
42
+ src << bufvar << ".safe_append='"
41
43
  src << "\n" * @newline_pending if @newline_pending > 0
42
44
  src << text.gsub(/['\\]/, '\\\\\&')
43
45
  src << "'.freeze;"
@@ -52,9 +54,9 @@ module ActionView
52
54
  flush_newline_if_pending(src)
53
55
 
54
56
  if (indicator == "==") || @escape
55
- src << "@output_buffer.safe_expr_append="
57
+ src << bufvar << ".safe_expr_append="
56
58
  else
57
- src << "@output_buffer.append="
59
+ src << bufvar << ".append="
58
60
  end
59
61
 
60
62
  if BLOCK_EXPR.match?(code)
@@ -76,7 +78,7 @@ module ActionView
76
78
 
77
79
  def flush_newline_if_pending(src)
78
80
  if @newline_pending > 0
79
- src << "@output_buffer.safe_append='#{"\n" * @newline_pending}'.freeze;"
81
+ src << bufvar << ".safe_append='#{"\n" * @newline_pending}'.freeze;"
80
82
  @newline_pending = 0
81
83
  end
82
84
  end
@@ -16,16 +16,6 @@ module ActionView
16
16
  # Do not escape templates of these mime types.
17
17
  class_attribute :escape_ignore_list, default: ["text/plain"]
18
18
 
19
- [self, singleton_class].each do |base|
20
- base.alias_method :escape_whitelist, :escape_ignore_list
21
- base.alias_method :escape_whitelist=, :escape_ignore_list=
22
-
23
- base.deprecate(
24
- escape_whitelist: "use #escape_ignore_list instead",
25
- :escape_whitelist= => "use #escape_ignore_list= instead"
26
- )
27
- end
28
-
29
19
  ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")
30
20
 
31
21
  def self.call(template, source)
@@ -45,7 +35,7 @@ module ActionView
45
35
  # wrong, we can still find an encoding tag
46
36
  # (<%# encoding %>) inside the String using a regular
47
37
  # expression
48
- template_source = source.dup.force_encoding(Encoding::ASCII_8BIT)
38
+ template_source = source.b
49
39
 
50
40
  erb = template_source.gsub(ENCODING_TAG, "")
51
41
  encoding = $2
@@ -55,11 +45,17 @@ module ActionView
55
45
  # Always make sure we return a String in the default_internal
56
46
  erb.encode!
57
47
 
58
- self.class.erb_implementation.new(
59
- erb,
48
+ options = {
60
49
  escape: (self.class.escape_ignore_list.include? template.type),
61
50
  trim: (self.class.erb_trim_mode == "-")
62
- ).src
51
+ }
52
+
53
+ if ActionView::Base.annotate_rendered_view_with_filenames && template.format == :html
54
+ options[:preamble] = "@output_buffer.safe_append='<!-- BEGIN #{template.short_identifier} -->';"
55
+ options[:postamble] = "@output_buffer.safe_append='<!-- END #{template.short_identifier} -->';@output_buffer.to_s"
56
+ end
57
+
58
+ self.class.erb_implementation.new(erb, options).src
63
59
  end
64
60
 
65
61
  private
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/deprecation"
4
-
5
3
  module ActionView #:nodoc:
6
4
  # = Action View Template Handlers
7
5
  class Template #:nodoc:
@@ -26,35 +24,11 @@ module ActionView #:nodoc:
26
24
  @@template_extensions ||= @@template_handlers.keys
27
25
  end
28
26
 
29
- class LegacyHandlerWrapper < SimpleDelegator # :nodoc:
30
- def call(view, source)
31
- __getobj__.call(ActionView::Template::LegacyTemplate.new(view, source))
32
- end
33
- end
34
-
35
27
  # Register an object that knows how to handle template files with the given
36
28
  # extensions. This can be used to implement new template types.
37
29
  # The handler must respond to +:call+, which will be passed the template
38
30
  # and should return the rendered template as a String.
39
31
  def register_template_handler(*extensions, handler)
40
- params = if handler.is_a?(Proc)
41
- handler.parameters
42
- else
43
- handler.method(:call).parameters
44
- end
45
-
46
- unless params.find_all { |type, _| type == :req || type == :opt }.length >= 2
47
- ActiveSupport::Deprecation.warn <<~eowarn
48
- Single arity template handlers are deprecated. Template handlers must
49
- now accept two parameters, the view object and the source for the view object.
50
- Change:
51
- >> #{handler}.call(#{params.map(&:last).join(", ")})
52
- To:
53
- >> #{handler}.call(#{params.map(&:last).join(", ")}, source)
54
- eowarn
55
- handler = LegacyHandlerWrapper.new(handler)
56
- end
57
-
58
32
  raise(ArgumentError, "Extension is required") if extensions.empty?
59
33
  extensions.each do |extension|
60
34
  @@template_handlers[extension.to_sym] = handler
@@ -1,19 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/deprecation"
4
-
5
3
  module ActionView #:nodoc:
6
4
  # = Action View HTML Template
7
5
  class Template #:nodoc:
8
6
  class HTML #:nodoc:
9
7
  attr_reader :type
10
8
 
11
- def initialize(string, type = nil)
12
- unless type
13
- ActiveSupport::Deprecation.warn "ActionView::Template::HTML#initialize requires a type parameter"
14
- type = :html
15
- end
16
-
9
+ def initialize(string, type)
17
10
  @string = string.to_s
18
11
  @type = type
19
12
  end
@@ -35,9 +28,6 @@ module ActionView #:nodoc:
35
28
  def format
36
29
  @type
37
30
  end
38
-
39
- def formats; Array(format); end
40
- deprecate :formats
41
31
  end
42
32
  end
43
33
  end
@@ -20,9 +20,6 @@ module ActionView #:nodoc:
20
20
  def render(*args)
21
21
  ::File.read(@filename)
22
22
  end
23
-
24
- def formats; Array(format); end
25
- deprecate :formats
26
23
  end
27
24
  end
28
25
  end