actionview 6.0.6.1 → 6.1.7.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.
Potentially problematic release.
This version of actionview might be problematic. Click here for more details.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +226 -220
 - data/MIT-LICENSE +1 -2
 - data/lib/action_view/base.rb +18 -49
 - data/lib/action_view/cache_expiry.rb +1 -2
 - data/lib/action_view/dependency_tracker.rb +10 -4
 - data/lib/action_view/digestor.rb +3 -2
 - data/lib/action_view/gem_version.rb +3 -3
 - data/lib/action_view/helpers/asset_tag_helper.rb +57 -17
 - data/lib/action_view/helpers/asset_url_helper.rb +6 -4
 - data/lib/action_view/helpers/atom_feed_helper.rb +2 -1
 - data/lib/action_view/helpers/cache_helper.rb +10 -16
 - data/lib/action_view/helpers/date_helper.rb +6 -5
 - data/lib/action_view/helpers/form_helper.rb +66 -30
 - data/lib/action_view/helpers/form_options_helper.rb +7 -16
 - data/lib/action_view/helpers/form_tag_helper.rb +4 -3
 - data/lib/action_view/helpers/javascript_helper.rb +3 -3
 - data/lib/action_view/helpers/number_helper.rb +6 -6
 - data/lib/action_view/helpers/rendering_helper.rb +11 -3
 - data/lib/action_view/helpers/tag_helper.rb +98 -22
 - data/lib/action_view/helpers/tags/base.rb +10 -6
 - data/lib/action_view/helpers/tags/check_box.rb +1 -1
 - data/lib/action_view/helpers/tags/date_field.rb +1 -1
 - data/lib/action_view/helpers/tags/date_select.rb +2 -2
 - data/lib/action_view/helpers/tags/datetime_local_field.rb +1 -1
 - data/lib/action_view/helpers/tags/hidden_field.rb +4 -0
 - data/lib/action_view/helpers/tags/label.rb +4 -0
 - data/lib/action_view/helpers/tags/month_field.rb +1 -1
 - data/lib/action_view/helpers/tags/select.rb +1 -1
 - data/lib/action_view/helpers/tags/time_field.rb +1 -1
 - data/lib/action_view/helpers/tags/week_field.rb +1 -1
 - data/lib/action_view/helpers/text_helper.rb +2 -2
 - data/lib/action_view/helpers/translation_helper.rb +88 -50
 - data/lib/action_view/helpers/url_helper.rb +136 -24
 - data/lib/action_view/layouts.rb +3 -2
 - data/lib/action_view/log_subscriber.rb +26 -10
 - data/lib/action_view/lookup_context.rb +3 -18
 - data/lib/action_view/path_set.rb +0 -3
 - data/lib/action_view/railtie.rb +39 -46
 - data/lib/action_view/renderer/abstract_renderer.rb +93 -14
 - data/lib/action_view/renderer/collection_renderer.rb +196 -0
 - data/lib/action_view/renderer/object_renderer.rb +34 -0
 - data/lib/action_view/renderer/partial_renderer/collection_caching.rb +25 -26
 - data/lib/action_view/renderer/partial_renderer.rb +20 -282
 - data/lib/action_view/renderer/renderer.rb +44 -1
 - data/lib/action_view/renderer/streaming_template_renderer.rb +5 -1
 - data/lib/action_view/renderer/template_renderer.rb +15 -12
 - data/lib/action_view/rendering.rb +3 -1
 - data/lib/action_view/routing_url_for.rb +1 -1
 - data/lib/action_view/template/handlers/erb/erubi.rb +9 -7
 - data/lib/action_view/template/handlers/erb.rb +10 -14
 - data/lib/action_view/template/handlers.rb +0 -26
 - data/lib/action_view/template/html.rb +1 -11
 - data/lib/action_view/template/raw_file.rb +0 -3
 - data/lib/action_view/template/renderable.rb +24 -0
 - data/lib/action_view/template/resolver.rb +82 -40
 - data/lib/action_view/template/text.rb +0 -3
 - data/lib/action_view/template.rb +9 -49
 - data/lib/action_view/test_case.rb +18 -25
 - data/lib/action_view/testing/resolvers.rb +10 -31
 - data/lib/action_view/unbound_template.rb +3 -3
 - data/lib/action_view/view_paths.rb +34 -36
 - data/lib/action_view.rb +4 -1
 - data/lib/assets/compiled/rails-ujs.js +2 -2
 - metadata +14 -11
 
| 
         @@ -105,7 +105,7 @@ module ActionView 
     | 
|
| 
       105 
105 
     | 
    
         
             
                      end
         
     | 
| 
       106 
106 
     | 
    
         | 
| 
       107 
107 
     | 
    
         
             
                      def tag_name(multiple = false, index = nil)
         
     | 
| 
       108 
     | 
    
         
            -
                        # a little duplication to construct  
     | 
| 
      
 108 
     | 
    
         
            +
                        # a little duplication to construct fewer strings
         
     | 
| 
       109 
109 
     | 
    
         
             
                        case
         
     | 
| 
       110 
110 
     | 
    
         
             
                        when @object_name.empty?
         
     | 
| 
       111 
111 
     | 
    
         
             
                          "#{sanitized_method_name}#{multiple ? "[]" : ""}"
         
     | 
| 
         @@ -117,7 +117,7 @@ module ActionView 
     | 
|
| 
       117 
117 
     | 
    
         
             
                      end
         
     | 
| 
       118 
118 
     | 
    
         | 
| 
       119 
119 
     | 
    
         
             
                      def tag_id(index = nil)
         
     | 
| 
       120 
     | 
    
         
            -
                        # a little duplication to construct  
     | 
| 
      
 120 
     | 
    
         
            +
                        # a little duplication to construct fewer strings
         
     | 
| 
       121 
121 
     | 
    
         
             
                        case
         
     | 
| 
       122 
122 
     | 
    
         
             
                        when @object_name.empty?
         
     | 
| 
       123 
123 
     | 
    
         
             
                          sanitized_method_name.dup
         
     | 
| 
         @@ -129,11 +129,11 @@ module ActionView 
     | 
|
| 
       129 
129 
     | 
    
         
             
                      end
         
     | 
| 
       130 
130 
     | 
    
         | 
| 
       131 
131 
     | 
    
         
             
                      def sanitized_object_name
         
     | 
| 
       132 
     | 
    
         
            -
                        @sanitized_object_name ||= @object_name.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_"). 
     | 
| 
      
 132 
     | 
    
         
            +
                        @sanitized_object_name ||= @object_name.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").delete_suffix("_")
         
     | 
| 
       133 
133 
     | 
    
         
             
                      end
         
     | 
| 
       134 
134 
     | 
    
         | 
| 
       135 
135 
     | 
    
         
             
                      def sanitized_method_name
         
     | 
| 
       136 
     | 
    
         
            -
                        @sanitized_method_name ||= @method_name. 
     | 
| 
      
 136 
     | 
    
         
            +
                        @sanitized_method_name ||= @method_name.delete_suffix("?")
         
     | 
| 
       137 
137 
     | 
    
         
             
                      end
         
     | 
| 
       138 
138 
     | 
    
         | 
| 
       139 
139 
     | 
    
         
             
                      def sanitized_value(value)
         
     | 
| 
         @@ -153,7 +153,7 @@ module ActionView 
     | 
|
| 
       153 
153 
     | 
    
         
             
                        select = content_tag("select", add_options(option_tags, options, value), html_options)
         
     | 
| 
       154 
154 
     | 
    
         | 
| 
       155 
155 
     | 
    
         
             
                        if html_options["multiple"] && options.fetch(:include_hidden, true)
         
     | 
| 
       156 
     | 
    
         
            -
                          tag("input", disabled: html_options["disabled"], name: html_options["name"], type: "hidden", value: "") + select
         
     | 
| 
      
 156 
     | 
    
         
            +
                          tag("input", disabled: html_options["disabled"], name: html_options["name"], type: "hidden", value: "", autocomplete: "off") + select
         
     | 
| 
       157 
157 
     | 
    
         
             
                        else
         
     | 
| 
       158 
158 
     | 
    
         
             
                          select
         
     | 
| 
       159 
159 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -166,8 +166,11 @@ module ActionView 
     | 
|
| 
       166 
166 
     | 
    
         | 
| 
       167 
167 
     | 
    
         
             
                      def add_options(option_tags, options, value = nil)
         
     | 
| 
       168 
168 
     | 
    
         
             
                        if options[:include_blank]
         
     | 
| 
       169 
     | 
    
         
            -
                           
     | 
| 
      
 169 
     | 
    
         
            +
                          content = (options[:include_blank] if options[:include_blank].is_a?(String))
         
     | 
| 
      
 170 
     | 
    
         
            +
                          label = (" " unless content)
         
     | 
| 
      
 171 
     | 
    
         
            +
                          option_tags = tag_builder.content_tag_string("option", content, value: "", label: label) + "\n" + option_tags
         
     | 
| 
       170 
172 
     | 
    
         
             
                        end
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
       171 
174 
     | 
    
         
             
                        if value.blank? && options[:prompt]
         
     | 
| 
       172 
175 
     | 
    
         
             
                          tag_options = { value: "" }.tap do |prompt_opts|
         
     | 
| 
       173 
176 
     | 
    
         
             
                            prompt_opts[:disabled] = true if options[:disabled] == ""
         
     | 
| 
         @@ -175,6 +178,7 @@ module ActionView 
     | 
|
| 
       175 
178 
     | 
    
         
             
                          end
         
     | 
| 
       176 
179 
     | 
    
         
             
                          option_tags = tag_builder.content_tag_string("option", prompt_text(options[:prompt]), tag_options) + "\n" + option_tags
         
     | 
| 
       177 
180 
     | 
    
         
             
                        end
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
       178 
182 
     | 
    
         
             
                        option_tags
         
     | 
| 
       179 
183 
     | 
    
         
             
                      end
         
     | 
| 
       180 
184 
     | 
    
         | 
| 
         @@ -57,7 +57,7 @@ module ActionView 
     | 
|
| 
       57 
57 
     | 
    
         
             
                      end
         
     | 
| 
       58 
58 
     | 
    
         | 
| 
       59 
59 
     | 
    
         
             
                      def hidden_field_for_checkbox(options)
         
     | 
| 
       60 
     | 
    
         
            -
                        @unchecked_value ? tag("input", options.slice("name", "disabled", "form").merge!("type" => "hidden", "value" => @unchecked_value)) : "".html_safe
         
     | 
| 
      
 60 
     | 
    
         
            +
                        @unchecked_value ? tag("input", options.slice("name", "disabled", "form").merge!("type" => "hidden", "value" => @unchecked_value, "autocomplete" => "off")) : "".html_safe
         
     | 
| 
       61 
61 
     | 
    
         
             
                      end
         
     | 
| 
       62 
62 
     | 
    
         
             
                  end
         
     | 
| 
       63 
63 
     | 
    
         
             
                end
         
     | 
| 
         @@ -13,7 +13,7 @@ module ActionView 
     | 
|
| 
       13 
13 
     | 
    
         
             
                    end
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
                    def render
         
     | 
| 
       16 
     | 
    
         
            -
                      error_wrapping(datetime_selector(@options, @html_options). 
     | 
| 
      
 16 
     | 
    
         
            +
                      error_wrapping(datetime_selector(@options, @html_options).public_send("select_#{select_type}").html_safe)
         
     | 
| 
       17 
17 
     | 
    
         
             
                    end
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         
             
                    class << self
         
     | 
| 
         @@ -58,7 +58,7 @@ module ActionView 
     | 
|
| 
       58 
58 
     | 
    
         
             
                          time = Time.current
         
     | 
| 
       59 
59 
     | 
    
         | 
| 
       60 
60 
     | 
    
         
             
                          [:year, :month, :day, :hour, :min, :sec].each do |key|
         
     | 
| 
       61 
     | 
    
         
            -
                            default[key] ||= time. 
     | 
| 
      
 61 
     | 
    
         
            +
                            default[key] ||= time.public_send(key)
         
     | 
| 
       62 
62 
     | 
    
         
             
                          end
         
     | 
| 
       63 
63 
     | 
    
         | 
| 
       64 
64 
     | 
    
         
             
                          Time.utc(
         
     | 
| 
         @@ -105,7 +105,7 @@ module ActionView 
     | 
|
| 
       105 
105 
     | 
    
         
             
                  # Highlights one or more +phrases+ everywhere in +text+ by inserting it into
         
     | 
| 
       106 
106 
     | 
    
         
             
                  # a <tt>:highlighter</tt> string. The highlighter can be specialized by passing <tt>:highlighter</tt>
         
     | 
| 
       107 
107 
     | 
    
         
             
                  # as a single-quoted string with <tt>\1</tt> where the phrase is to be inserted (defaults to
         
     | 
| 
       108 
     | 
    
         
            -
                  #  
     | 
| 
      
 108 
     | 
    
         
            +
                  # <tt><mark>\1</mark></tt>) or passing a block that receives each matched term. By default +text+
         
     | 
| 
       109 
109 
     | 
    
         
             
                  # is sanitized to prevent possible XSS attacks. If the input is trustworthy, passing false
         
     | 
| 
       110 
110 
     | 
    
         
             
                  # for <tt>:sanitize</tt> will turn sanitizing off.
         
     | 
| 
       111 
111 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -228,7 +228,7 @@ module ActionView 
     | 
|
| 
       228 
228 
     | 
    
         
             
                  #   pluralize(2, 'Person', locale: :de)
         
     | 
| 
       229 
229 
     | 
    
         
             
                  #   # => 2 Personen
         
     | 
| 
       230 
230 
     | 
    
         
             
                  def pluralize(count, singular, plural_arg = nil, plural: plural_arg, locale: I18n.locale)
         
     | 
| 
       231 
     | 
    
         
            -
                    word = if count == 1 || count.to_s 
     | 
| 
      
 231 
     | 
    
         
            +
                    word = if count == 1 || count.to_s.match?(/^1(\.0+)?$/)
         
     | 
| 
       232 
232 
     | 
    
         
             
                      singular
         
     | 
| 
       233 
233 
     | 
    
         
             
                    else
         
     | 
| 
       234 
234 
     | 
    
         
             
                      plural || singular.pluralize(locale)
         
     | 
| 
         @@ -1,8 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require "action_view/helpers/tag_helper"
         
     | 
| 
       4 
     | 
    
         
            -
            require "active_support/core_ext/ 
     | 
| 
       5 
     | 
    
         
            -
            require "i18n/exceptions"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "active_support/core_ext/symbol/starts_ends_with"
         
     | 
| 
       6 
5 
     | 
    
         | 
| 
       7 
6 
     | 
    
         
             
            module ActionView
         
     | 
| 
       8 
7 
     | 
    
         
             
              # = Action View Translation Helpers
         
     | 
| 
         @@ -57,64 +56,58 @@ module ActionView 
     | 
|
| 
       57 
56 
     | 
    
         
             
                  # that include HTML tags so that you know what kind of output to expect
         
     | 
| 
       58 
57 
     | 
    
         
             
                  # when you call translate in a template and translators know which keys
         
     | 
| 
       59 
58 
     | 
    
         
             
                  # they can provide HTML values for.
         
     | 
| 
      
 59 
     | 
    
         
            +
                  #
         
     | 
| 
      
 60 
     | 
    
         
            +
                  # To access the translated text along with the fully resolved
         
     | 
| 
      
 61 
     | 
    
         
            +
                  # translation key, <tt>translate</tt> accepts a block:
         
     | 
| 
      
 62 
     | 
    
         
            +
                  #
         
     | 
| 
      
 63 
     | 
    
         
            +
                  #     <%= translate(".relative_key") do |translation, resolved_key| %>
         
     | 
| 
      
 64 
     | 
    
         
            +
                  #       <span title="<%= resolved_key %>"><%= translation %></span>
         
     | 
| 
      
 65 
     | 
    
         
            +
                  #     <% end %>
         
     | 
| 
      
 66 
     | 
    
         
            +
                  #
         
     | 
| 
      
 67 
     | 
    
         
            +
                  # This enables annotate translated text to be aware of the scope it was
         
     | 
| 
      
 68 
     | 
    
         
            +
                  # resolved against.
         
     | 
| 
      
 69 
     | 
    
         
            +
                  #
         
     | 
| 
       60 
70 
     | 
    
         
             
                  def translate(key, **options)
         
     | 
| 
       61 
     | 
    
         
            -
                    if  
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
                      options[:default] = remaining_defaults unless remaining_defaults.first.kind_of?(Symbol)
         
     | 
| 
       64 
     | 
    
         
            -
                    end
         
     | 
| 
      
 71 
     | 
    
         
            +
                    return key.map { |k| translate(k, **options) } if key.is_a?(Array)
         
     | 
| 
      
 72 
     | 
    
         
            +
                    key = key&.to_s unless key.is_a?(Symbol)
         
     | 
| 
       65 
73 
     | 
    
         | 
| 
       66 
     | 
    
         
            -
                     
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
                    # Note: `raise_error` refers to us re-raising the error in this method. I18n is forced to raise by default.
         
     | 
| 
       69 
     | 
    
         
            -
                    if options[:raise] == false
         
     | 
| 
       70 
     | 
    
         
            -
                      raise_error = false
         
     | 
| 
       71 
     | 
    
         
            -
                      i18n_raise = false
         
     | 
| 
       72 
     | 
    
         
            -
                    else
         
     | 
| 
       73 
     | 
    
         
            -
                      raise_error = options[:raise] || ActionView::Base.raise_on_missing_translations
         
     | 
| 
       74 
     | 
    
         
            -
                      i18n_raise = true
         
     | 
| 
      
 74 
     | 
    
         
            +
                    alternatives = if options.key?(:default)
         
     | 
| 
      
 75 
     | 
    
         
            +
                      options[:default].is_a?(Array) ? options.delete(:default).compact : [options.delete(:default)]
         
     | 
| 
       75 
76 
     | 
    
         
             
                    end
         
     | 
| 
       76 
77 
     | 
    
         | 
| 
       77 
     | 
    
         
            -
                    if  
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
      
 78 
     | 
    
         
            +
                    options[:raise] = true if options[:raise].nil? && ActionView::Base.raise_on_missing_translations
         
     | 
| 
      
 79 
     | 
    
         
            +
                    default = MISSING_TRANSLATION
         
     | 
| 
       79 
80 
     | 
    
         | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
       83 
     | 
    
         
            -
                        end
         
     | 
| 
      
 81 
     | 
    
         
            +
                    translation = while key || alternatives.present?
         
     | 
| 
      
 82 
     | 
    
         
            +
                      if alternatives.blank? && !options[:raise].nil?
         
     | 
| 
      
 83 
     | 
    
         
            +
                        default = NO_DEFAULT # let I18n handle missing translation
         
     | 
| 
       84 
84 
     | 
    
         
             
                      end
         
     | 
| 
       85 
85 
     | 
    
         | 
| 
       86 
     | 
    
         
            -
                       
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
                      translation = I18n.translate(scope_key_by_partial(key), **html_safe_options.merge(raise: i18n_raise))
         
     | 
| 
      
 86 
     | 
    
         
            +
                      key = scope_key_by_partial(key)
         
     | 
| 
       89 
87 
     | 
    
         | 
| 
       90 
     | 
    
         
            -
                      if  
     | 
| 
       91 
     | 
    
         
            -
                        options 
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
                         
     | 
| 
      
 88 
     | 
    
         
            +
                      if html_safe_translation_key?(key)
         
     | 
| 
      
 89 
     | 
    
         
            +
                        html_safe_options ||= html_escape_translation_options(options)
         
     | 
| 
      
 90 
     | 
    
         
            +
                        translated = I18n.translate(key, **html_safe_options, default: default)
         
     | 
| 
      
 91 
     | 
    
         
            +
                        break html_safe_translation(translated) unless translated.equal?(MISSING_TRANSLATION)
         
     | 
| 
       94 
92 
     | 
    
         
             
                      else
         
     | 
| 
       95 
     | 
    
         
            -
                         
     | 
| 
      
 93 
     | 
    
         
            +
                        translated = I18n.translate(key, **options, default: default)
         
     | 
| 
      
 94 
     | 
    
         
            +
                        break translated unless translated.equal?(MISSING_TRANSLATION)
         
     | 
| 
       96 
95 
     | 
    
         
             
                      end
         
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
                       
     | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
       100 
     | 
    
         
            -
                  rescue I18n::MissingTranslationData => e
         
     | 
| 
       101 
     | 
    
         
            -
                    if remaining_defaults.present?
         
     | 
| 
       102 
     | 
    
         
            -
                      translate remaining_defaults.shift, **options.merge(default: remaining_defaults)
         
     | 
| 
       103 
     | 
    
         
            -
                    else
         
     | 
| 
       104 
     | 
    
         
            -
                      raise e if raise_error
         
     | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
                      keys = I18n.normalize_keys(e.locale, e.key, e.options[:scope])
         
     | 
| 
       107 
     | 
    
         
            -
                      title = +"translation missing: #{keys.join('.')}"
         
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
                      interpolations = options.except(:default, :scope)
         
     | 
| 
       110 
     | 
    
         
            -
                      if interpolations.any?
         
     | 
| 
       111 
     | 
    
         
            -
                        title << ", " << interpolations.map { |k, v| "#{k}: #{ERB::Util.html_escape(v)}" }.join(", ")
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                      if alternatives.present? && !alternatives.first.is_a?(Symbol)
         
     | 
| 
      
 98 
     | 
    
         
            +
                        break alternatives.first && I18n.translate(**options, default: alternatives)
         
     | 
| 
       112 
99 
     | 
    
         
             
                      end
         
     | 
| 
       113 
100 
     | 
    
         | 
| 
       114 
     | 
    
         
            -
                       
     | 
| 
      
 101 
     | 
    
         
            +
                      first_key ||= key
         
     | 
| 
      
 102 
     | 
    
         
            +
                      key = alternatives&.shift
         
     | 
| 
      
 103 
     | 
    
         
            +
                    end
         
     | 
| 
       115 
104 
     | 
    
         | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
      
 105 
     | 
    
         
            +
                    if key.nil? && !first_key.nil?
         
     | 
| 
      
 106 
     | 
    
         
            +
                      translation = missing_translation(first_key, options)
         
     | 
| 
      
 107 
     | 
    
         
            +
                      key = first_key
         
     | 
| 
       117 
108 
     | 
    
         
             
                    end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                    block_given? ? yield(translation, key) : translation
         
     | 
| 
       118 
111 
     | 
    
         
             
                  end
         
     | 
| 
       119 
112 
     | 
    
         
             
                  alias :t :translate
         
     | 
| 
       120 
113 
     | 
    
         | 
| 
         @@ -131,13 +124,19 @@ module ActionView 
     | 
|
| 
       131 
124 
     | 
    
         
             
                    MISSING_TRANSLATION = Object.new
         
     | 
| 
       132 
125 
     | 
    
         
             
                    private_constant :MISSING_TRANSLATION
         
     | 
| 
       133 
126 
     | 
    
         | 
| 
      
 127 
     | 
    
         
            +
                    NO_DEFAULT = [].freeze
         
     | 
| 
      
 128 
     | 
    
         
            +
                    private_constant :NO_DEFAULT
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                    def self.i18n_option?(name)
         
     | 
| 
      
 131 
     | 
    
         
            +
                      (@i18n_option_names ||= I18n::RESERVED_KEYS.to_set).include?(name)
         
     | 
| 
      
 132 
     | 
    
         
            +
                    end
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
       134 
134 
     | 
    
         
             
                    def scope_key_by_partial(key)
         
     | 
| 
       135 
     | 
    
         
            -
                       
     | 
| 
       136 
     | 
    
         
            -
                      if stringified_key.first == "."
         
     | 
| 
      
 135 
     | 
    
         
            +
                      if key&.start_with?(".")
         
     | 
| 
       137 
136 
     | 
    
         
             
                        if @virtual_path
         
     | 
| 
       138 
137 
     | 
    
         
             
                          @_scope_key_by_partial_cache ||= {}
         
     | 
| 
       139 
138 
     | 
    
         
             
                          @_scope_key_by_partial_cache[@virtual_path] ||= @virtual_path.gsub(%r{/_?}, ".")
         
     | 
| 
       140 
     | 
    
         
            -
                          "#{@_scope_key_by_partial_cache[@virtual_path]}#{ 
     | 
| 
      
 139 
     | 
    
         
            +
                          "#{@_scope_key_by_partial_cache[@virtual_path]}#{key}"
         
     | 
| 
       141 
140 
     | 
    
         
             
                        else
         
     | 
| 
       142 
141 
     | 
    
         
             
                          raise "Cannot use t(#{key.inspect}) shortcut because path is not available"
         
     | 
| 
       143 
142 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -146,8 +145,47 @@ module ActionView 
     | 
|
| 
       146 
145 
     | 
    
         
             
                      end
         
     | 
| 
       147 
146 
     | 
    
         
             
                    end
         
     | 
| 
       148 
147 
     | 
    
         | 
| 
      
 148 
     | 
    
         
            +
                    def html_escape_translation_options(options)
         
     | 
| 
      
 149 
     | 
    
         
            +
                      return options if options.empty?
         
     | 
| 
      
 150 
     | 
    
         
            +
                      html_safe_options = options.dup
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                      options.each do |name, value|
         
     | 
| 
      
 153 
     | 
    
         
            +
                        unless TranslationHelper.i18n_option?(name) || (name == :count && value.is_a?(Numeric))
         
     | 
| 
      
 154 
     | 
    
         
            +
                          html_safe_options[name] = ERB::Util.html_escape(value.to_s)
         
     | 
| 
      
 155 
     | 
    
         
            +
                        end
         
     | 
| 
      
 156 
     | 
    
         
            +
                      end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                      html_safe_options
         
     | 
| 
      
 159 
     | 
    
         
            +
                    end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
       149 
161 
     | 
    
         
             
                    def html_safe_translation_key?(key)
         
     | 
| 
       150 
     | 
    
         
            -
                      /(?:_|\b)html\z/.match?(key 
     | 
| 
      
 162 
     | 
    
         
            +
                      /(?:_|\b)html\z/.match?(key)
         
     | 
| 
      
 163 
     | 
    
         
            +
                    end
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                    def html_safe_translation(translation)
         
     | 
| 
      
 166 
     | 
    
         
            +
                      if translation.respond_to?(:map)
         
     | 
| 
      
 167 
     | 
    
         
            +
                        translation.map { |element| element.respond_to?(:html_safe) ? element.html_safe : element }
         
     | 
| 
      
 168 
     | 
    
         
            +
                      else
         
     | 
| 
      
 169 
     | 
    
         
            +
                        translation.respond_to?(:html_safe) ? translation.html_safe : translation
         
     | 
| 
      
 170 
     | 
    
         
            +
                      end
         
     | 
| 
      
 171 
     | 
    
         
            +
                    end
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                    def missing_translation(key, options)
         
     | 
| 
      
 174 
     | 
    
         
            +
                      keys = I18n.normalize_keys(options[:locale] || I18n.locale, key, options[:scope])
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
                      title = +"translation missing: #{keys.join(".")}"
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
                      options.each do |name, value|
         
     | 
| 
      
 179 
     | 
    
         
            +
                        unless name == :scope
         
     | 
| 
      
 180 
     | 
    
         
            +
                          title << ", " << name.to_s << ": " << ERB::Util.html_escape(value)
         
     | 
| 
      
 181 
     | 
    
         
            +
                        end
         
     | 
| 
      
 182 
     | 
    
         
            +
                      end
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
                      if ActionView::Base.debug_missing_translation
         
     | 
| 
      
 185 
     | 
    
         
            +
                        content_tag("span", keys.last.to_s.titleize, class: "translation_missing", title: title)
         
     | 
| 
      
 186 
     | 
    
         
            +
                      else
         
     | 
| 
      
 187 
     | 
    
         
            +
                        title
         
     | 
| 
      
 188 
     | 
    
         
            +
                      end
         
     | 
| 
       151 
189 
     | 
    
         
             
                    end
         
     | 
| 
       152 
190 
     | 
    
         
             
                end
         
     | 
| 
       153 
191 
     | 
    
         
             
              end
         
     | 
| 
         @@ -45,7 +45,7 @@ module ActionView 
     | 
|
| 
       45 
45 
     | 
    
         
             
                  def _back_url # :nodoc:
         
     | 
| 
       46 
46 
     | 
    
         
             
                    _filtered_referrer || "javascript:history.back()"
         
     | 
| 
       47 
47 
     | 
    
         
             
                  end
         
     | 
| 
       48 
     | 
    
         
            -
                   
     | 
| 
      
 48 
     | 
    
         
            +
                  private :_back_url
         
     | 
| 
       49 
49 
     | 
    
         | 
| 
       50 
50 
     | 
    
         
             
                  def _filtered_referrer # :nodoc:
         
     | 
| 
       51 
51 
     | 
    
         
             
                    if controller.respond_to?(:request)
         
     | 
| 
         @@ -56,12 +56,12 @@ module ActionView 
     | 
|
| 
       56 
56 
     | 
    
         
             
                    end
         
     | 
| 
       57 
57 
     | 
    
         
             
                  rescue URI::InvalidURIError
         
     | 
| 
       58 
58 
     | 
    
         
             
                  end
         
     | 
| 
       59 
     | 
    
         
            -
                   
     | 
| 
      
 59 
     | 
    
         
            +
                  private :_filtered_referrer
         
     | 
| 
       60 
60 
     | 
    
         | 
| 
       61 
61 
     | 
    
         
             
                  # Creates an anchor element of the given +name+ using a URL created by the set of +options+.
         
     | 
| 
       62 
62 
     | 
    
         
             
                  # See the valid options in the documentation for +url_for+. It's also possible to
         
     | 
| 
       63 
     | 
    
         
            -
                  # pass a String instead of an options hash, which generates an anchor element that uses the
         
     | 
| 
       64 
     | 
    
         
            -
                  # value of the String as the href for the link. Using a <tt>:back</tt> Symbol instead
         
     | 
| 
      
 63 
     | 
    
         
            +
                  # pass a \String instead of an options hash, which generates an anchor element that uses the
         
     | 
| 
      
 64 
     | 
    
         
            +
                  # value of the \String as the href for the link. Using a <tt>:back</tt> \Symbol instead
         
     | 
| 
       65 
65 
     | 
    
         
             
                  # of an options hash will generate a link to the referrer (a JavaScript back link
         
     | 
| 
       66 
66 
     | 
    
         
             
                  # will be used in place of a referrer if none exists). If +nil+ is passed as the name
         
     | 
| 
       67 
67 
     | 
    
         
             
                  # the value of the link itself will become the name.
         
     | 
| 
         @@ -177,7 +177,7 @@ module ActionView 
     | 
|
| 
       177 
177 
     | 
    
         
             
                  #   # => <a href="/searches?query=ruby+on+rails">Ruby on Rails search</a>
         
     | 
| 
       178 
178 
     | 
    
         
             
                  #
         
     | 
| 
       179 
179 
     | 
    
         
             
                  #   link_to "Nonsense search", searches_path(foo: "bar", baz: "quux")
         
     | 
| 
       180 
     | 
    
         
            -
                  #   # => <a href="/searches?foo=bar& 
     | 
| 
      
 180 
     | 
    
         
            +
                  #   # => <a href="/searches?foo=bar&baz=quux">Nonsense search</a>
         
     | 
| 
       181 
181 
     | 
    
         
             
                  #
         
     | 
| 
       182 
182 
     | 
    
         
             
                  # The only option specific to +link_to+ (<tt>:method</tt>) is used as follows:
         
     | 
| 
       183 
183 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -226,7 +226,7 @@ module ActionView 
     | 
|
| 
       226 
226 
     | 
    
         
             
                  # The +options+ hash accepts the same options as +url_for+.
         
     | 
| 
       227 
227 
     | 
    
         
             
                  #
         
     | 
| 
       228 
228 
     | 
    
         
             
                  # There are a few special +html_options+:
         
     | 
| 
       229 
     | 
    
         
            -
                  # * <tt>:method</tt> - Symbol of HTTP verb. Supported verbs are <tt>:post</tt>, <tt>:get</tt>,
         
     | 
| 
      
 229 
     | 
    
         
            +
                  # * <tt>:method</tt> - \Symbol of HTTP verb. Supported verbs are <tt>:post</tt>, <tt>:get</tt>,
         
     | 
| 
       230 
230 
     | 
    
         
             
                  #   <tt>:delete</tt>, <tt>:patch</tt>, and <tt>:put</tt>. By default it will be <tt>:post</tt>.
         
     | 
| 
       231 
231 
     | 
    
         
             
                  # * <tt>:disabled</tt> - If set to true, it will generate a disabled button.
         
     | 
| 
       232 
232 
     | 
    
         
             
                  # * <tt>:data</tt> - This option can be used to add custom data attributes.
         
     | 
| 
         @@ -235,7 +235,7 @@ module ActionView 
     | 
|
| 
       235 
235 
     | 
    
         
             
                  # * <tt>:form</tt> - This hash will be form attributes
         
     | 
| 
       236 
236 
     | 
    
         
             
                  # * <tt>:form_class</tt> - This controls the class of the form within which the submit button will
         
     | 
| 
       237 
237 
     | 
    
         
             
                  #   be placed
         
     | 
| 
       238 
     | 
    
         
            -
                  # * <tt>:params</tt> - Hash of parameters to be rendered as hidden fields within the form.
         
     | 
| 
      
 238 
     | 
    
         
            +
                  # * <tt>:params</tt> - \Hash of parameters to be rendered as hidden fields within the form.
         
     | 
| 
       239 
239 
     | 
    
         
             
                  #
         
     | 
| 
       240 
240 
     | 
    
         
             
                  # ==== Data attributes
         
     | 
| 
       241 
241 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -290,7 +290,7 @@ module ActionView 
     | 
|
| 
       290 
290 
     | 
    
         
             
                  #
         
     | 
| 
       291 
291 
     | 
    
         
             
                  #
         
     | 
| 
       292 
292 
     | 
    
         
             
                  #   <%= button_to('Destroy', 'http://www.example.com',
         
     | 
| 
       293 
     | 
    
         
            -
                  #             method:  
     | 
| 
      
 293 
     | 
    
         
            +
                  #             method: :delete, remote: true, data: { confirm: 'Are you sure?', disable_with: 'loading...' }) %>
         
     | 
| 
       294 
294 
     | 
    
         
             
                  #   # => "<form class='button_to' method='post' action='http://www.example.com' data-remote='true'>
         
     | 
| 
       295 
295 
     | 
    
         
             
                  #   #       <input name='_method' value='delete' type='hidden' />
         
     | 
| 
       296 
296 
     | 
    
         
             
                  #   #       <input value='Destroy' type='submit' data-disable-with='loading...' data-confirm='Are you sure?' />
         
     | 
| 
         @@ -337,7 +337,8 @@ module ActionView 
     | 
|
| 
       337 
337 
     | 
    
         
             
                    inner_tags = method_tag.safe_concat(button).safe_concat(request_token_tag)
         
     | 
| 
       338 
338 
     | 
    
         
             
                    if params
         
     | 
| 
       339 
339 
     | 
    
         
             
                      to_form_params(params).each do |param|
         
     | 
| 
       340 
     | 
    
         
            -
                        inner_tags.safe_concat tag(:input, type: "hidden", name: param[:name], value: param[:value] 
     | 
| 
      
 340 
     | 
    
         
            +
                        inner_tags.safe_concat tag(:input, type: "hidden", name: param[:name], value: param[:value],
         
     | 
| 
      
 341 
     | 
    
         
            +
                                                   autocomplete: "off")
         
     | 
| 
       341 
342 
     | 
    
         
             
                      end
         
     | 
| 
       342 
343 
     | 
    
         
             
                    end
         
     | 
| 
       343 
344 
     | 
    
         
             
                    content_tag("form", inner_tags, form_options)
         
     | 
| 
         @@ -412,8 +413,7 @@ module ActionView 
     | 
|
| 
       412 
413 
     | 
    
         
             
                  # Creates a link tag of the given +name+ using a URL created by the set of
         
     | 
| 
       413 
414 
     | 
    
         
             
                  # +options+ if +condition+ is true, otherwise only the name is
         
     | 
| 
       414 
415 
     | 
    
         
             
                  # returned. To specialize the default behavior, you can pass a block that
         
     | 
| 
       415 
     | 
    
         
            -
                  # accepts the name or the full argument list for + 
     | 
| 
       416 
     | 
    
         
            -
                  # in +link_to_unless+).
         
     | 
| 
      
 416 
     | 
    
         
            +
                  # accepts the name or the full argument list for +link_to_if+.
         
     | 
| 
       417 
417 
     | 
    
         
             
                  #
         
     | 
| 
       418 
418 
     | 
    
         
             
                  # ==== Examples
         
     | 
| 
       419 
419 
     | 
    
         
             
                  #   <%= link_to_if(@current_user.nil?, "Login", { controller: "sessions", action: "new" }) %>
         
     | 
| 
         @@ -540,7 +540,7 @@ module ActionView 
     | 
|
| 
       540 
540 
     | 
    
         
             
                  #
         
     | 
| 
       541 
541 
     | 
    
         
             
                  # We can also pass in the symbol arguments instead of strings.
         
     | 
| 
       542 
542 
     | 
    
         
             
                  #
         
     | 
| 
       543 
     | 
    
         
            -
                  def current_page?(options, check_parameters: false)
         
     | 
| 
      
 543 
     | 
    
         
            +
                  def current_page?(options = nil, check_parameters: false, **options_as_kwargs)
         
     | 
| 
       544 
544 
     | 
    
         
             
                    unless request
         
     | 
| 
       545 
545 
     | 
    
         
             
                      raise "You cannot use helpers that need to determine the current " \
         
     | 
| 
       546 
546 
     | 
    
         
             
                            "page unless your view context provides a Request object " \
         
     | 
| 
         @@ -549,28 +549,135 @@ module ActionView 
     | 
|
| 
       549 
549 
     | 
    
         | 
| 
       550 
550 
     | 
    
         
             
                    return false unless request.get? || request.head?
         
     | 
| 
       551 
551 
     | 
    
         | 
| 
      
 552 
     | 
    
         
            +
                    options ||= options_as_kwargs
         
     | 
| 
       552 
553 
     | 
    
         
             
                    check_parameters ||= options.is_a?(Hash) && options.delete(:check_parameters)
         
     | 
| 
       553 
     | 
    
         
            -
                    url_string = URI. 
     | 
| 
      
 554 
     | 
    
         
            +
                    url_string = URI::DEFAULT_PARSER.unescape(url_for(options)).force_encoding(Encoding::BINARY)
         
     | 
| 
       554 
555 
     | 
    
         | 
| 
       555 
556 
     | 
    
         
             
                    # We ignore any extra parameters in the request_uri if the
         
     | 
| 
       556 
557 
     | 
    
         
             
                    # submitted URL doesn't have any either. This lets the function
         
     | 
| 
       557 
558 
     | 
    
         
             
                    # work with things like ?order=asc
         
     | 
| 
       558 
559 
     | 
    
         
             
                    # the behaviour can be disabled with check_parameters: true
         
     | 
| 
       559 
560 
     | 
    
         
             
                    request_uri = url_string.index("?") || check_parameters ? request.fullpath : request.path
         
     | 
| 
       560 
     | 
    
         
            -
                    request_uri = URI. 
     | 
| 
      
 561 
     | 
    
         
            +
                    request_uri = URI::DEFAULT_PARSER.unescape(request_uri).force_encoding(Encoding::BINARY)
         
     | 
| 
       561 
562 
     | 
    
         | 
| 
       562 
     | 
    
         
            -
                    if  
     | 
| 
       563 
     | 
    
         
            -
                       
     | 
| 
       564 
     | 
    
         
            -
                      request_uri.chomp!("/")
         
     | 
| 
      
 563 
     | 
    
         
            +
                    if %r{^\w+://}.match?(url_string)
         
     | 
| 
      
 564 
     | 
    
         
            +
                      request_uri = +"#{request.protocol}#{request.host_with_port}#{request_uri}"
         
     | 
| 
       565 
565 
     | 
    
         
             
                    end
         
     | 
| 
       566 
566 
     | 
    
         | 
| 
       567 
     | 
    
         
            -
                     
     | 
| 
       568 
     | 
    
         
            -
             
     | 
| 
       569 
     | 
    
         
            -
             
     | 
| 
       570 
     | 
    
         
            -
             
     | 
| 
      
 567 
     | 
    
         
            +
                    remove_trailing_slash!(url_string)
         
     | 
| 
      
 568 
     | 
    
         
            +
                    remove_trailing_slash!(request_uri)
         
     | 
| 
      
 569 
     | 
    
         
            +
             
     | 
| 
      
 570 
     | 
    
         
            +
                    url_string == request_uri
         
     | 
| 
      
 571 
     | 
    
         
            +
                  end
         
     | 
| 
      
 572 
     | 
    
         
            +
             
     | 
| 
      
 573 
     | 
    
         
            +
                  if RUBY_VERSION.start_with?("2.7")
         
     | 
| 
      
 574 
     | 
    
         
            +
                    using Module.new {
         
     | 
| 
      
 575 
     | 
    
         
            +
                      refine UrlHelper do
         
     | 
| 
      
 576 
     | 
    
         
            +
                        alias :_current_page? :current_page?
         
     | 
| 
      
 577 
     | 
    
         
            +
                      end
         
     | 
| 
      
 578 
     | 
    
         
            +
                    }
         
     | 
| 
      
 579 
     | 
    
         
            +
             
     | 
| 
      
 580 
     | 
    
         
            +
                    def current_page?(*args) # :nodoc:
         
     | 
| 
      
 581 
     | 
    
         
            +
                      options = args.pop
         
     | 
| 
      
 582 
     | 
    
         
            +
                      options.is_a?(Hash) ? _current_page?(*args, **options) : _current_page?(*args, options)
         
     | 
| 
       571 
583 
     | 
    
         
             
                    end
         
     | 
| 
       572 
584 
     | 
    
         
             
                  end
         
     | 
| 
       573 
585 
     | 
    
         | 
| 
      
 586 
     | 
    
         
            +
                  # Creates an SMS anchor link tag to the specified +phone_number+, which is
         
     | 
| 
      
 587 
     | 
    
         
            +
                  # also used as the name of the link unless +name+ is specified. Additional
         
     | 
| 
      
 588 
     | 
    
         
            +
                  # HTML attributes for the link can be passed in +html_options+.
         
     | 
| 
      
 589 
     | 
    
         
            +
                  #
         
     | 
| 
      
 590 
     | 
    
         
            +
                  # When clicked, an SMS message is prepopulated with the passed phone number
         
     | 
| 
      
 591 
     | 
    
         
            +
                  # and optional +body+ value.
         
     | 
| 
      
 592 
     | 
    
         
            +
                  #
         
     | 
| 
      
 593 
     | 
    
         
            +
                  # +sms_to+ has a +body+ option for customizing the SMS message itself by
         
     | 
| 
      
 594 
     | 
    
         
            +
                  # passing special keys to +html_options+.
         
     | 
| 
      
 595 
     | 
    
         
            +
                  #
         
     | 
| 
      
 596 
     | 
    
         
            +
                  # ==== Options
         
     | 
| 
      
 597 
     | 
    
         
            +
                  # * <tt>:body</tt> - Preset the body of the message.
         
     | 
| 
      
 598 
     | 
    
         
            +
                  #
         
     | 
| 
      
 599 
     | 
    
         
            +
                  # ==== Examples
         
     | 
| 
      
 600 
     | 
    
         
            +
                  #   sms_to "5155555785"
         
     | 
| 
      
 601 
     | 
    
         
            +
                  #   # => <a href="sms:5155555785;">5155555785</a>
         
     | 
| 
      
 602 
     | 
    
         
            +
                  #
         
     | 
| 
      
 603 
     | 
    
         
            +
                  #   sms_to "5155555785", "Text me"
         
     | 
| 
      
 604 
     | 
    
         
            +
                  #   # => <a href="sms:5155555785;">Text me</a>
         
     | 
| 
      
 605 
     | 
    
         
            +
                  #
         
     | 
| 
      
 606 
     | 
    
         
            +
                  #   sms_to "5155555785", "Text me",
         
     | 
| 
      
 607 
     | 
    
         
            +
                  #          body: "Hello Jim I have a question about your product."
         
     | 
| 
      
 608 
     | 
    
         
            +
                  #   # => <a href="sms:5155555785;?body=Hello%20Jim%20I%20have%20a%20question%20about%20your%20product">Text me</a>
         
     | 
| 
      
 609 
     | 
    
         
            +
                  #
         
     | 
| 
      
 610 
     | 
    
         
            +
                  # You can use a block as well if your link target is hard to fit into the name parameter. \ERB example:
         
     | 
| 
      
 611 
     | 
    
         
            +
                  #
         
     | 
| 
      
 612 
     | 
    
         
            +
                  #   <%= sms_to "5155555785" do %>
         
     | 
| 
      
 613 
     | 
    
         
            +
                  #     <strong>Text me:</strong>
         
     | 
| 
      
 614 
     | 
    
         
            +
                  #   <% end %>
         
     | 
| 
      
 615 
     | 
    
         
            +
                  #   # => <a href="sms:5155555785;">
         
     | 
| 
      
 616 
     | 
    
         
            +
                  #          <strong>Text me:</strong>
         
     | 
| 
      
 617 
     | 
    
         
            +
                  #        </a>
         
     | 
| 
      
 618 
     | 
    
         
            +
                  def sms_to(phone_number, name = nil, html_options = {}, &block)
         
     | 
| 
      
 619 
     | 
    
         
            +
                    html_options, name = name, nil if block_given?
         
     | 
| 
      
 620 
     | 
    
         
            +
                    html_options = (html_options || {}).stringify_keys
         
     | 
| 
      
 621 
     | 
    
         
            +
             
     | 
| 
      
 622 
     | 
    
         
            +
                    extras = %w{ body }.map! { |item|
         
     | 
| 
      
 623 
     | 
    
         
            +
                      option = html_options.delete(item).presence || next
         
     | 
| 
      
 624 
     | 
    
         
            +
                      "#{item.dasherize}=#{ERB::Util.url_encode(option)}"
         
     | 
| 
      
 625 
     | 
    
         
            +
                    }.compact
         
     | 
| 
      
 626 
     | 
    
         
            +
                    extras = extras.empty? ? "" : "?&" + extras.join("&")
         
     | 
| 
      
 627 
     | 
    
         
            +
             
     | 
| 
      
 628 
     | 
    
         
            +
                    encoded_phone_number = ERB::Util.url_encode(phone_number)
         
     | 
| 
      
 629 
     | 
    
         
            +
                    html_options["href"] = "sms:#{encoded_phone_number};#{extras}"
         
     | 
| 
      
 630 
     | 
    
         
            +
             
     | 
| 
      
 631 
     | 
    
         
            +
                    content_tag("a", name || phone_number, html_options, &block)
         
     | 
| 
      
 632 
     | 
    
         
            +
                  end
         
     | 
| 
      
 633 
     | 
    
         
            +
             
     | 
| 
      
 634 
     | 
    
         
            +
                  # Creates a TEL anchor link tag to the specified +phone_number+, which is
         
     | 
| 
      
 635 
     | 
    
         
            +
                  # also used as the name of the link unless +name+ is specified. Additional
         
     | 
| 
      
 636 
     | 
    
         
            +
                  # HTML attributes for the link can be passed in +html_options+.
         
     | 
| 
      
 637 
     | 
    
         
            +
                  #
         
     | 
| 
      
 638 
     | 
    
         
            +
                  # When clicked, the default app to make calls is opened, and it
         
     | 
| 
      
 639 
     | 
    
         
            +
                  # is prepopulated with the passed phone number and optional
         
     | 
| 
      
 640 
     | 
    
         
            +
                  # +country_code+ value.
         
     | 
| 
      
 641 
     | 
    
         
            +
                  #
         
     | 
| 
      
 642 
     | 
    
         
            +
                  # +phone_to+ has an optional +country_code+ option which automatically adds the country
         
     | 
| 
      
 643 
     | 
    
         
            +
                  # code as well as the + sign in the phone numer that gets prepopulated,
         
     | 
| 
      
 644 
     | 
    
         
            +
                  # for example if +country_code: "01"+  +\+01+ will be prepended to the
         
     | 
| 
      
 645 
     | 
    
         
            +
                  # phone numer, by passing special keys to +html_options+.
         
     | 
| 
      
 646 
     | 
    
         
            +
                  #
         
     | 
| 
      
 647 
     | 
    
         
            +
                  # ==== Options
         
     | 
| 
      
 648 
     | 
    
         
            +
                  # * <tt>:country_code</tt> - Prepends the country code to the number
         
     | 
| 
      
 649 
     | 
    
         
            +
                  #
         
     | 
| 
      
 650 
     | 
    
         
            +
                  # ==== Examples
         
     | 
| 
      
 651 
     | 
    
         
            +
                  #   phone_to "1234567890"
         
     | 
| 
      
 652 
     | 
    
         
            +
                  #   # => <a href="tel:1234567890">1234567890</a>
         
     | 
| 
      
 653 
     | 
    
         
            +
                  #
         
     | 
| 
      
 654 
     | 
    
         
            +
                  #   phone_to "1234567890", "Phone me"
         
     | 
| 
      
 655 
     | 
    
         
            +
                  #   # => <a href="tel:134567890">Phone me</a>
         
     | 
| 
      
 656 
     | 
    
         
            +
                  #
         
     | 
| 
      
 657 
     | 
    
         
            +
                  #   phone_to "1234567890", "Phone me", country_code: "01"
         
     | 
| 
      
 658 
     | 
    
         
            +
                  #   # => <a href="tel:+015155555785">Phone me</a>
         
     | 
| 
      
 659 
     | 
    
         
            +
                  #
         
     | 
| 
      
 660 
     | 
    
         
            +
                  # You can use a block as well if your link target is hard to fit into the name parameter. \ERB example:
         
     | 
| 
      
 661 
     | 
    
         
            +
                  #
         
     | 
| 
      
 662 
     | 
    
         
            +
                  #   <%= phone_to "1234567890" do %>
         
     | 
| 
      
 663 
     | 
    
         
            +
                  #     <strong>Phone me:</strong>
         
     | 
| 
      
 664 
     | 
    
         
            +
                  #   <% end %>
         
     | 
| 
      
 665 
     | 
    
         
            +
                  #   # => <a href="tel:1234567890">
         
     | 
| 
      
 666 
     | 
    
         
            +
                  #          <strong>Phone me:</strong>
         
     | 
| 
      
 667 
     | 
    
         
            +
                  #        </a>
         
     | 
| 
      
 668 
     | 
    
         
            +
                  def phone_to(phone_number, name = nil, html_options = {}, &block)
         
     | 
| 
      
 669 
     | 
    
         
            +
                    html_options, name = name, nil if block_given?
         
     | 
| 
      
 670 
     | 
    
         
            +
                    html_options = (html_options || {}).stringify_keys
         
     | 
| 
      
 671 
     | 
    
         
            +
             
     | 
| 
      
 672 
     | 
    
         
            +
                    country_code = html_options.delete("country_code").presence
         
     | 
| 
      
 673 
     | 
    
         
            +
                    country_code = country_code.nil? ? "" : "+#{ERB::Util.url_encode(country_code)}"
         
     | 
| 
      
 674 
     | 
    
         
            +
             
     | 
| 
      
 675 
     | 
    
         
            +
                    encoded_phone_number = ERB::Util.url_encode(phone_number)
         
     | 
| 
      
 676 
     | 
    
         
            +
                    html_options["href"] = "tel:#{country_code}#{encoded_phone_number}"
         
     | 
| 
      
 677 
     | 
    
         
            +
             
     | 
| 
      
 678 
     | 
    
         
            +
                    content_tag("a", name || phone_number, html_options, &block)
         
     | 
| 
      
 679 
     | 
    
         
            +
                  end
         
     | 
| 
      
 680 
     | 
    
         
            +
             
     | 
| 
       574 
681 
     | 
    
         
             
                  private
         
     | 
| 
       575 
682 
     | 
    
         
             
                    def convert_options_to_data_attributes(options, html_options)
         
     | 
| 
       576 
683 
     | 
    
         
             
                      if html_options
         
     | 
| 
         @@ -594,7 +701,7 @@ module ActionView 
     | 
|
| 
       594 
701 
     | 
    
         
             
                    end
         
     | 
| 
       595 
702 
     | 
    
         | 
| 
       596 
703 
     | 
    
         
             
                    def add_method_to_attributes!(html_options, method)
         
     | 
| 
       597 
     | 
    
         
            -
                      if method_not_get_method?(method) && html_options["rel"] 
     | 
| 
      
 704 
     | 
    
         
            +
                      if method_not_get_method?(method) && !html_options["rel"]&.match?(/nofollow/)
         
     | 
| 
       598 
705 
     | 
    
         
             
                        if html_options["rel"].blank?
         
     | 
| 
       599 
706 
     | 
    
         
             
                          html_options["rel"] = "nofollow"
         
     | 
| 
       600 
707 
     | 
    
         
             
                        else
         
     | 
| 
         @@ -620,14 +727,14 @@ module ActionView 
     | 
|
| 
       620 
727 
     | 
    
         
             
                    def token_tag(token = nil, form_options: {})
         
     | 
| 
       621 
728 
     | 
    
         
             
                      if token != false && defined?(protect_against_forgery?) && protect_against_forgery?
         
     | 
| 
       622 
729 
     | 
    
         
             
                        token ||= form_authenticity_token(form_options: form_options)
         
     | 
| 
       623 
     | 
    
         
            -
                        tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token)
         
     | 
| 
      
 730 
     | 
    
         
            +
                        tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token, autocomplete: "off")
         
     | 
| 
       624 
731 
     | 
    
         
             
                      else
         
     | 
| 
       625 
732 
     | 
    
         
             
                        ""
         
     | 
| 
       626 
733 
     | 
    
         
             
                      end
         
     | 
| 
       627 
734 
     | 
    
         
             
                    end
         
     | 
| 
       628 
735 
     | 
    
         | 
| 
       629 
736 
     | 
    
         
             
                    def method_tag(method)
         
     | 
| 
       630 
     | 
    
         
            -
                      tag("input", type: "hidden", name: "_method", value: method.to_s)
         
     | 
| 
      
 737 
     | 
    
         
            +
                      tag("input", type: "hidden", name: "_method", value: method.to_s, autocomplete: "off")
         
     | 
| 
       631 
738 
     | 
    
         
             
                    end
         
     | 
| 
       632 
739 
     | 
    
         | 
| 
       633 
740 
     | 
    
         
             
                    # Returns an array of hashes each containing :name and :value keys
         
     | 
| 
         @@ -671,6 +778,11 @@ module ActionView 
     | 
|
| 
       671 
778 
     | 
    
         | 
| 
       672 
779 
     | 
    
         
             
                      params.sort_by { |pair| pair[:name] }
         
     | 
| 
       673 
780 
     | 
    
         
             
                    end
         
     | 
| 
      
 781 
     | 
    
         
            +
             
     | 
| 
      
 782 
     | 
    
         
            +
                    def remove_trailing_slash!(url_string)
         
     | 
| 
      
 783 
     | 
    
         
            +
                      trailing_index = (url_string.index("?") || 0) - 1
         
     | 
| 
      
 784 
     | 
    
         
            +
                      url_string[trailing_index] = "" if url_string[trailing_index] == "/"
         
     | 
| 
      
 785 
     | 
    
         
            +
                    end
         
     | 
| 
       674 
786 
     | 
    
         
             
                end
         
     | 
| 
       675 
787 
     | 
    
         
             
              end
         
     | 
| 
       676 
788 
     | 
    
         
             
            end
         
     |