actionview 7.0.8.7 → 7.2.2.1

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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +59 -454
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/app/assets/javascripts/rails-ujs.esm.js +686 -0
  6. data/app/assets/javascripts/rails-ujs.js +630 -0
  7. data/lib/action_view/base.rb +52 -14
  8. data/lib/action_view/buffers.rb +106 -8
  9. data/lib/action_view/cache_expiry.rb +44 -41
  10. data/lib/action_view/context.rb +1 -1
  11. data/lib/action_view/dependency_tracker/{ripper_tracker.rb → ruby_tracker.rb} +4 -3
  12. data/lib/action_view/dependency_tracker.rb +1 -1
  13. data/lib/action_view/deprecator.rb +7 -0
  14. data/lib/action_view/digestor.rb +1 -1
  15. data/lib/action_view/gem_version.rb +4 -4
  16. data/lib/action_view/helpers/active_model_helper.rb +1 -1
  17. data/lib/action_view/helpers/asset_tag_helper.rb +151 -55
  18. data/lib/action_view/helpers/asset_url_helper.rb +6 -5
  19. data/lib/action_view/helpers/atom_feed_helper.rb +5 -5
  20. data/lib/action_view/helpers/cache_helper.rb +7 -13
  21. data/lib/action_view/helpers/capture_helper.rb +30 -10
  22. data/lib/action_view/helpers/content_exfiltration_prevention_helper.rb +70 -0
  23. data/lib/action_view/helpers/controller_helper.rb +6 -0
  24. data/lib/action_view/helpers/csp_helper.rb +2 -2
  25. data/lib/action_view/helpers/csrf_helper.rb +3 -3
  26. data/lib/action_view/helpers/date_helper.rb +17 -19
  27. data/lib/action_view/helpers/debug_helper.rb +3 -3
  28. data/lib/action_view/helpers/form_helper.rb +248 -214
  29. data/lib/action_view/helpers/form_options_helper.rb +2 -1
  30. data/lib/action_view/helpers/form_tag_helper.rb +125 -58
  31. data/lib/action_view/helpers/javascript_helper.rb +1 -0
  32. data/lib/action_view/helpers/number_helper.rb +37 -330
  33. data/lib/action_view/helpers/output_safety_helper.rb +6 -6
  34. data/lib/action_view/helpers/rendering_helper.rb +1 -1
  35. data/lib/action_view/helpers/sanitize_helper.rb +51 -21
  36. data/lib/action_view/helpers/tag_helper.rb +210 -42
  37. data/lib/action_view/helpers/tags/base.rb +11 -52
  38. data/lib/action_view/helpers/tags/collection_check_boxes.rb +1 -0
  39. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +1 -0
  40. data/lib/action_view/helpers/tags/collection_select.rb +3 -0
  41. data/lib/action_view/helpers/tags/date_field.rb +1 -1
  42. data/lib/action_view/helpers/tags/date_select.rb +2 -0
  43. data/lib/action_view/helpers/tags/datetime_field.rb +14 -6
  44. data/lib/action_view/helpers/tags/datetime_local_field.rb +11 -2
  45. data/lib/action_view/helpers/tags/grouped_collection_select.rb +3 -0
  46. data/lib/action_view/helpers/tags/month_field.rb +1 -1
  47. data/lib/action_view/helpers/tags/select.rb +3 -0
  48. data/lib/action_view/helpers/tags/select_renderer.rb +56 -0
  49. data/lib/action_view/helpers/tags/time_field.rb +1 -1
  50. data/lib/action_view/helpers/tags/time_zone_select.rb +3 -0
  51. data/lib/action_view/helpers/tags/week_field.rb +1 -1
  52. data/lib/action_view/helpers/tags/weekday_select.rb +3 -0
  53. data/lib/action_view/helpers/tags.rb +2 -0
  54. data/lib/action_view/helpers/text_helper.rb +157 -85
  55. data/lib/action_view/helpers/translation_helper.rb +3 -3
  56. data/lib/action_view/helpers/url_helper.rb +35 -80
  57. data/lib/action_view/helpers.rb +2 -0
  58. data/lib/action_view/layouts.rb +8 -8
  59. data/lib/action_view/log_subscriber.rb +57 -36
  60. data/lib/action_view/lookup_context.rb +29 -13
  61. data/lib/action_view/path_registry.rb +57 -0
  62. data/lib/action_view/path_set.rb +13 -14
  63. data/lib/action_view/railtie.rb +25 -3
  64. data/lib/action_view/record_identifier.rb +15 -8
  65. data/lib/action_view/render_parser/prism_render_parser.rb +127 -0
  66. data/lib/action_view/{ripper_ast_parser.rb → render_parser/ripper_render_parser.rb} +156 -13
  67. data/lib/action_view/render_parser.rb +21 -169
  68. data/lib/action_view/renderer/abstract_renderer.rb +2 -2
  69. data/lib/action_view/renderer/collection_renderer.rb +10 -2
  70. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +2 -1
  71. data/lib/action_view/renderer/partial_renderer.rb +2 -1
  72. data/lib/action_view/renderer/renderer.rb +34 -38
  73. data/lib/action_view/renderer/streaming_template_renderer.rb +3 -2
  74. data/lib/action_view/renderer/template_renderer.rb +3 -2
  75. data/lib/action_view/rendering.rb +26 -8
  76. data/lib/action_view/template/error.rb +14 -1
  77. data/lib/action_view/template/handlers/builder.rb +4 -4
  78. data/lib/action_view/template/handlers/erb/erubi.rb +23 -27
  79. data/lib/action_view/template/handlers/erb.rb +73 -1
  80. data/lib/action_view/template/handlers.rb +1 -1
  81. data/lib/action_view/template/html.rb +1 -1
  82. data/lib/action_view/template/raw_file.rb +1 -1
  83. data/lib/action_view/template/renderable.rb +8 -2
  84. data/lib/action_view/template/resolver.rb +9 -3
  85. data/lib/action_view/template/text.rb +1 -1
  86. data/lib/action_view/template/types.rb +25 -34
  87. data/lib/action_view/template.rb +278 -55
  88. data/lib/action_view/template_path.rb +2 -0
  89. data/lib/action_view/test_case.rb +181 -28
  90. data/lib/action_view/unbound_template.rb +17 -7
  91. data/lib/action_view/version.rb +1 -1
  92. data/lib/action_view/view_paths.rb +15 -24
  93. data/lib/action_view.rb +4 -1
  94. metadata +26 -26
  95. data/lib/assets/compiled/rails-ujs.js +0 -777
@@ -8,8 +8,9 @@ require "active_support/core_ext/array/wrap"
8
8
  require "action_view/helpers/text_helper"
9
9
 
10
10
  module ActionView
11
- # = Action View Form Option Helpers
12
11
  module Helpers # :nodoc:
12
+ # = Action View Form Option \Helpers
13
+ #
13
14
  # Provides a number of methods for turning different kinds of containers into a set of option tags.
14
15
  #
15
16
  # The <tt>collection_select</tt>, <tt>select</tt> and <tt>time_zone_select</tt> methods take an <tt>options</tt> parameter, a hash:
@@ -1,14 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "cgi"
4
+ require "action_view/helpers/content_exfiltration_prevention_helper"
4
5
  require "action_view/helpers/url_helper"
5
6
  require "action_view/helpers/text_helper"
6
7
  require "active_support/core_ext/string/output_safety"
7
8
  require "active_support/core_ext/module/attribute_accessors"
8
9
 
9
10
  module ActionView
10
- # = Action View Form Tag Helpers
11
11
  module Helpers # :nodoc:
12
+ # = Action View Form Tag \Helpers
13
+ #
12
14
  # Provides a number of methods for creating form tags that don't rely on an Active Record object assigned to the template like
13
15
  # FormHelper does. Instead, you provide the names and values manually.
14
16
  #
@@ -19,6 +21,7 @@ module ActionView
19
21
 
20
22
  include UrlHelper
21
23
  include TextHelper
24
+ include ContentExfiltrationPreventionHelper
22
25
 
23
26
  mattr_accessor :embed_authenticity_token_in_remote_forms
24
27
  self.embed_authenticity_token_in_remote_forms = nil
@@ -88,11 +91,11 @@ module ActionView
88
91
  # attribute name.
89
92
  #
90
93
  # <%= label_tag :post, :title %>
91
- # <%= text_field_tag :post, :title, aria: { describedby: field_id(:post, :title, :error) } %>
94
+ # <%= text_field :post, :title, aria: { describedby: field_id(:post, :title, :error) } %>
92
95
  # <%= tag.span("is blank", id: field_id(:post, :title, :error) %>
93
96
  #
94
97
  # In the example above, the <tt><input type="text"></tt> element built by
95
- # the call to <tt>text_field_tag</tt> declares an
98
+ # the call to <tt>text_field</tt> declares an
96
99
  # <tt>aria-describedby</tt> attribute referencing the <tt><span></tt>
97
100
  # element, sharing a common <tt>id</tt> root (<tt>post_title</tt>, in this
98
101
  # case).
@@ -120,11 +123,11 @@ module ActionView
120
123
  # Return the value generated by the <tt>FormBuilder</tt> for the given
121
124
  # attribute name.
122
125
  #
123
- # <%= text_field_tag :post, :title, name: field_name(:post, :title, :subtitle) %>
124
- # <%# => <input type="text" name="post[title][subtitle]">
126
+ # <%= text_field :post, :title, name: field_name(:post, :title, :subtitle) %>
127
+ # <%# => <input type="text" name="post[title][subtitle]"> %>
125
128
  #
126
- # <%= text_field_tag :post, :tag, name: field_name(:post, :tag, multiple: true) %>
127
- # <%# => <input type="text" name="post[tag][]">
129
+ # <%= text_field :post, :tag, name: field_name(:post, :tag, multiple: true) %>
130
+ # <%# => <input type="text" name="post[tag][]"> %>
128
131
  #
129
132
  def field_name(object_name, method_name, *method_names, multiple: false, index: nil)
130
133
  names = method_names.map! { |name| "[#{name}]" }.join
@@ -420,9 +423,17 @@ module ActionView
420
423
  content_tag :textarea, content.to_s.html_safe, { "name" => name, "id" => sanitize_to_id(name) }.update(options)
421
424
  end
422
425
 
426
+ ##
427
+ # :call-seq:
428
+ # check_box_tag(name, options = {})
429
+ # check_box_tag(name, value, options = {})
430
+ # check_box_tag(name, value, checked, options = {})
431
+ #
423
432
  # Creates a check box form input tag.
424
433
  #
425
434
  # ==== Options
435
+ # * <tt>:value</tt> - The value of the input. Defaults to <tt>"1"</tt>.
436
+ # * <tt>:checked</tt> - If set to true, the checkbox will be checked by default.
426
437
  # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
427
438
  # * Any other key creates standard HTML options for the tag.
428
439
  #
@@ -441,16 +452,27 @@ module ActionView
441
452
  #
442
453
  # check_box_tag 'eula', 'accepted', false, disabled: true
443
454
  # # => <input disabled="disabled" id="eula" name="eula" type="checkbox" value="accepted" />
444
- def check_box_tag(name, value = "1", checked = false, options = {})
455
+ def check_box_tag(name, *args)
456
+ if args.length >= 4
457
+ raise ArgumentError, "wrong number of arguments (given #{args.length + 1}, expected 1..4)"
458
+ end
459
+ options = args.extract_options!
460
+ value, checked = args.empty? ? ["1", false] : [*args, false]
445
461
  html_options = { "type" => "checkbox", "name" => name, "id" => sanitize_to_id(name), "value" => value }.update(options.stringify_keys)
446
462
  html_options["checked"] = "checked" if checked
447
463
  tag :input, html_options
448
464
  end
449
465
 
466
+ ##
467
+ # :call-seq:
468
+ # radio_button_tag(name, value, options = {})
469
+ # radio_button_tag(name, value, checked, options = {})
470
+ #
450
471
  # Creates a radio button; use groups of radio buttons named the same to allow users to
451
472
  # select from a group of options.
452
473
  #
453
474
  # ==== Options
475
+ # * <tt>:checked</tt> - If set to true, the radio button will be selected by default.
454
476
  # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
455
477
  # * Any other key creates standard HTML options for the tag.
456
478
  #
@@ -466,7 +488,12 @@ module ActionView
466
488
  #
467
489
  # radio_button_tag 'color', "green", true, class: "color_input"
468
490
  # # => <input checked="checked" class="color_input" id="color_green" name="color" type="radio" value="green" />
469
- def radio_button_tag(name, value, checked = false, options = {})
491
+ def radio_button_tag(name, value, *args)
492
+ if args.length >= 3
493
+ raise ArgumentError, "wrong number of arguments (given #{args.length + 2}, expected 2..4)"
494
+ end
495
+ options = args.extract_options!
496
+ checked = args.empty? ? false : args.first
470
497
  html_options = { "type" => "radio", "name" => name, "id" => "#{sanitize_to_id(name)}_#{sanitize_to_id(value)}", "value" => value }.update(options.stringify_keys)
471
498
  html_options["checked"] = "checked" if checked
472
499
  tag :input, html_options
@@ -495,25 +522,6 @@ module ActionView
495
522
  # submit_tag "Edit", class: "edit_button"
496
523
  # # => <input class="edit_button" data-disable-with="Edit" name="commit" type="submit" value="Edit" />
497
524
  #
498
- # ==== Deprecated: Rails UJS attributes
499
- #
500
- # Prior to Rails 7, Rails shipped with the JavaScript library called @rails/ujs on by default. Following Rails 7,
501
- # this library is no longer on by default. This library integrated with the following options:
502
- #
503
- # * <tt>confirm: 'question?'</tt> - If present the unobtrusive JavaScript
504
- # drivers will provide a prompt with the question specified. If the user accepts,
505
- # the form is processed normally, otherwise no action is taken.
506
- # * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a
507
- # disabled version of the submit button when the form is submitted. This feature is
508
- # provided by the unobtrusive JavaScript driver. To disable this feature for a single submit tag
509
- # pass <tt>:data => { disable_with: false }</tt> Defaults to value attribute.
510
- #
511
- # submit_tag "Complete sale", data: { disable_with: "Submitting..." }
512
- # # => <input name="commit" data-disable-with="Submitting..." type="submit" value="Complete sale" />
513
- #
514
- # submit_tag "Save", data: { confirm: "Are you sure?" }
515
- # # => <input name='commit' type='submit' value='Save' data-disable-with="Save" data-confirm="Are you sure?" />
516
- #
517
525
  def submit_tag(value = "Save changes", options = {})
518
526
  options = options.deep_stringify_keys
519
527
  tag_options = { "type" => "submit", "name" => "commit", "value" => value }.update(options)
@@ -555,26 +563,6 @@ module ActionView
555
563
  # # <strong>Ask me!</strong>
556
564
  # # </button>
557
565
  #
558
- # ==== Deprecated: Rails UJS attributes
559
- #
560
- # Prior to Rails 7, Rails shipped with a JavaScript library called @rails/ujs on by default. Following Rails 7,
561
- # this library is no longer on by default. This library integrated with the following options:
562
- #
563
- # * <tt>confirm: 'question?'</tt> - If present, the
564
- # unobtrusive JavaScript drivers will provide a prompt with
565
- # the question specified. If the user accepts, the form is
566
- # processed normally, otherwise no action is taken.
567
- # * <tt>:disable_with</tt> - Value of this parameter will be
568
- # used as the value for a disabled version of the submit
569
- # button when the form is submitted. This feature is provided
570
- # by the unobtrusive JavaScript driver.
571
- #
572
- # button_tag "Save", data: { confirm: "Are you sure?" }
573
- # # => <button name="button" type="submit" data-confirm="Are you sure?">Save</button>
574
- #
575
- # button_tag "Checkout", data: { disable_with: "Please wait..." }
576
- # # => <button data-disable-with="Please wait..." name="button" type="submit">Checkout</button>
577
- #
578
566
  def button_tag(content_or_options = nil, options = nil, &block)
579
567
  if content_or_options.is_a? Hash
580
568
  options = content_or_options
@@ -648,11 +636,13 @@ module ActionView
648
636
  # <% end %>
649
637
  # # => <fieldset class="format"><p><input id="name" name="name" type="text" /></p></fieldset>
650
638
  def field_set_tag(legend = nil, options = nil, &block)
651
- output = tag(:fieldset, options, true)
652
- output.safe_concat(content_tag("legend", legend)) unless legend.blank?
653
- output.concat(capture(&block)) if block_given?
654
- output.safe_concat("</fieldset>")
639
+ content = []
640
+ content << content_tag("legend", legend) unless legend.blank?
641
+ content << capture(&block) if block_given?
642
+
643
+ content_tag(:fieldset, safe_join(content), options)
655
644
  end
645
+ alias_method :fieldset_tag, :field_set_tag
656
646
 
657
647
  # Creates a text field of type "color".
658
648
  #
@@ -735,14 +725,14 @@ module ActionView
735
725
  # date_field_tag 'name'
736
726
  # # => <input id="name" name="name" type="date" />
737
727
  #
738
- # date_field_tag 'date', '01/01/2014'
739
- # # => <input id="date" name="date" type="date" value="01/01/2014" />
728
+ # date_field_tag 'date', '2014-12-31'
729
+ # # => <input id="date" name="date" type="date" value="2014-12-31" />
740
730
  #
741
731
  # date_field_tag 'date', nil, class: 'special_input'
742
732
  # # => <input class="special_input" id="date" name="date" type="date" />
743
733
  #
744
- # date_field_tag 'date', '01/01/2014', class: 'special_input', disabled: true
745
- # # => <input disabled="disabled" class="special_input" id="date" name="date" type="date" value="01/01/2014" />
734
+ # date_field_tag 'date', '2014-12-31', class: 'special_input', disabled: true
735
+ # # => <input disabled="disabled" class="special_input" id="date" name="date" type="date" value="2014-12-31" />
746
736
  def date_field_tag(name, value = nil, options = {})
747
737
  text_field_tag(name, value, options.merge(type: :date))
748
738
  end
@@ -757,6 +747,23 @@ module ActionView
757
747
  # * <tt>:max</tt> - The maximum acceptable value.
758
748
  # * <tt>:step</tt> - The acceptable value granularity.
759
749
  # * <tt>:include_seconds</tt> - Include seconds and ms in the output timestamp format (true by default).
750
+ #
751
+ # ==== Examples
752
+ #
753
+ # time_field_tag 'name'
754
+ # # => <input id="name" name="name" type="time" />
755
+ #
756
+ # time_field_tag 'time', '01:01'
757
+ # # => <input id="time" name="time" type="time" value="01:01" />
758
+ #
759
+ # time_field_tag 'time', nil, class: 'special_input'
760
+ # # => <input class="special_input" id="time" name="time" type="time" />
761
+ #
762
+ # time_field_tag 'time', '01:01', include_seconds: true
763
+ # # => <input id="time" name="time" type="time" value="01:01:00.000" />
764
+ #
765
+ # time_field_tag 'time', '01:01', min: '00:00', max: '23:59', step: 1
766
+ # # => <input id="time" max="23:59" min="00:00" name="time" step="1" type="time" value="01:01" />
760
767
  def time_field_tag(name, value = nil, options = {})
761
768
  text_field_tag(name, value, options.merge(type: :time))
762
769
  end
@@ -770,6 +777,21 @@ module ActionView
770
777
  # * <tt>:min</tt> - The minimum acceptable value.
771
778
  # * <tt>:max</tt> - The maximum acceptable value.
772
779
  # * <tt>:step</tt> - The acceptable value granularity.
780
+ # * <tt>:include_seconds</tt> - Include seconds in the output timestamp format (true by default).
781
+ #
782
+ # ==== Examples
783
+ #
784
+ # datetime_field_tag 'name'
785
+ # # => <input id="name" name="name" type="datetime-local" />
786
+ #
787
+ # datetime_field_tag 'datetime', '2014-01-01T01:01'
788
+ # # => <input id="datetime" name="datetime" type="datetime-local" value="2014-01-01T01:01" />
789
+ #
790
+ # datetime_field_tag 'datetime', nil, class: 'special_input'
791
+ # # => <input class="special_input" id="datetime" name="datetime" type="datetime-local" />
792
+ #
793
+ # datetime_field_tag 'datetime', '2014-01-01T01:01', class: 'special_input', disabled: true
794
+ # # => <input disabled="disabled" class="special_input" id="datetime" name="datetime" type="datetime-local" value="2014-01-01T01:01" />
773
795
  def datetime_field_tag(name, value = nil, options = {})
774
796
  text_field_tag(name, value, options.merge(type: "datetime-local"))
775
797
  end
@@ -785,6 +807,20 @@ module ActionView
785
807
  # * <tt>:min</tt> - The minimum acceptable value.
786
808
  # * <tt>:max</tt> - The maximum acceptable value.
787
809
  # * <tt>:step</tt> - The acceptable value granularity.
810
+ #
811
+ # ==== Examples
812
+ #
813
+ # month_field_tag 'name'
814
+ # # => <input id="name" name="name" type="month" />
815
+ #
816
+ # month_field_tag 'month', '2014-01'
817
+ # # => <input id="month" name="month" type="month" value="2014-01" />
818
+ #
819
+ # month_field_tag 'month', nil, class: 'special_input'
820
+ # # => <input class="special_input" id="month" name="month" type="month" />
821
+ #
822
+ # month_field_tag 'month', '2014-01', class: 'special_input', disabled: true
823
+ # # => <input disabled="disabled" class="special_input" id="month" name="month" type="month" value="2014-01" />
788
824
  def month_field_tag(name, value = nil, options = {})
789
825
  text_field_tag(name, value, options.merge(type: :month))
790
826
  end
@@ -798,6 +834,20 @@ module ActionView
798
834
  # * <tt>:min</tt> - The minimum acceptable value.
799
835
  # * <tt>:max</tt> - The maximum acceptable value.
800
836
  # * <tt>:step</tt> - The acceptable value granularity.
837
+ #
838
+ # ==== Examples
839
+ #
840
+ # week_field_tag 'name'
841
+ # # => <input id="name" name="name" type="week" />
842
+ #
843
+ # week_field_tag 'week', '2014-W01'
844
+ # # => <input id="week" name="week" type="week" value="2014-W01" />
845
+ #
846
+ # week_field_tag 'week', nil, class: 'special_input'
847
+ # # => <input class="special_input" id="week" name="week" type="week" />
848
+ #
849
+ # week_field_tag 'week', '2014-W01', class: 'special_input', disabled: true
850
+ # # => <input disabled="disabled" class="special_input" id="week" name="week" type="week" value="2014-W01" />
801
851
  def week_field_tag(name, value = nil, options = {})
802
852
  text_field_tag(name, value, options.merge(type: :week))
803
853
  end
@@ -906,6 +956,17 @@ module ActionView
906
956
  # ==== Options
907
957
  #
908
958
  # Supports the same options as #number_field_tag.
959
+ #
960
+ # ==== Examples
961
+ #
962
+ # range_field_tag 'quantity', '1'
963
+ # # => <input id="quantity" name="quantity" type="range" value="1" />
964
+ #
965
+ # range_field_tag 'quantity', in: 1...10
966
+ # # => <input id="quantity" name="quantity" min="1" max="9" type="range" />
967
+ #
968
+ # range_field_tag 'quantity', min: 1, max: 10, step: 2
969
+ # # => <input id="quantity" name="quantity" min="1" max="10" step="2" type="range"
909
970
  def range_field_tag(name, value = nil, options = {})
910
971
  number_field_tag(name, value, options.merge(type: :range))
911
972
  end
@@ -979,7 +1040,8 @@ module ActionView
979
1040
 
980
1041
  def form_tag_html(html_options)
981
1042
  extra_tags = extra_tags_for_form(html_options)
982
- tag(:form, html_options, true) + extra_tags
1043
+ html = tag(:form, html_options, true) + extra_tags
1044
+ prevent_content_exfiltration(html)
983
1045
  end
984
1046
 
985
1047
  def form_tag_with_body(html_options, content)
@@ -1009,9 +1071,14 @@ module ActionView
1009
1071
  end
1010
1072
 
1011
1073
  def convert_direct_upload_option_to_url(options)
1012
- if options.delete(:direct_upload) && respond_to?(:rails_direct_uploads_url)
1074
+ return options unless options.delete(:direct_upload)
1075
+
1076
+ if respond_to?(:rails_direct_uploads_url)
1013
1077
  options["data-direct-upload-url"] = rails_direct_uploads_url
1078
+ elsif respond_to?(:main_app) && main_app.respond_to?(:rails_direct_uploads_url)
1079
+ options["data-direct-upload-url"] = main_app.rails_direct_uploads_url
1014
1080
  end
1081
+
1015
1082
  options
1016
1083
  end
1017
1084
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module ActionView
4
4
  module Helpers # :nodoc:
5
+ # = Action View JavaScript \Helpers
5
6
  module JavaScriptHelper
6
7
  JS_ESCAPE_MAP = {
7
8
  "\\" => "\\\\",