actionview 8.0.2 → 8.1.0.beta1

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -57
  3. data/README.rdoc +1 -1
  4. data/lib/action_view/base.rb +4 -2
  5. data/lib/action_view/buffers.rb +1 -1
  6. data/lib/action_view/dependency_tracker/erb_tracker.rb +1 -1
  7. data/lib/action_view/dependency_tracker.rb +6 -1
  8. data/lib/action_view/gem_version.rb +3 -3
  9. data/lib/action_view/helpers/asset_tag_helper.rb +20 -4
  10. data/lib/action_view/helpers/atom_feed_helper.rb +1 -1
  11. data/lib/action_view/helpers/capture_helper.rb +2 -2
  12. data/lib/action_view/helpers/controller_helper.rb +6 -2
  13. data/lib/action_view/helpers/date_helper.rb +25 -1
  14. data/lib/action_view/helpers/form_helper.rb +2 -2
  15. data/lib/action_view/helpers/form_options_helper.rb +16 -14
  16. data/lib/action_view/helpers/form_tag_helper.rb +17 -9
  17. data/lib/action_view/helpers/javascript_helper.rb +5 -1
  18. data/lib/action_view/helpers/number_helper.rb +14 -0
  19. data/lib/action_view/helpers/tag_helper.rb +31 -34
  20. data/lib/action_view/helpers/tags/datetime_field.rb +1 -1
  21. data/lib/action_view/helpers/tags/hidden_field.rb +1 -1
  22. data/lib/action_view/helpers/tags/select.rb +6 -1
  23. data/lib/action_view/helpers/tags/select_renderer.rb +2 -2
  24. data/lib/action_view/helpers/text_helper.rb +10 -3
  25. data/lib/action_view/helpers/translation_helper.rb +6 -1
  26. data/lib/action_view/helpers/url_helper.rb +37 -9
  27. data/lib/action_view/locale/en.yml +3 -0
  28. data/lib/action_view/railtie.rb +11 -0
  29. data/lib/action_view/record_identifier.rb +21 -0
  30. data/lib/action_view/renderer/partial_renderer.rb +16 -0
  31. data/lib/action_view/renderer/streaming_template_renderer.rb +8 -1
  32. data/lib/action_view/template/error.rb +7 -3
  33. data/lib/action_view/template/handlers/erb/erubi.rb +1 -1
  34. data/lib/action_view/template/handlers/erb.rb +36 -11
  35. data/lib/action_view/template/raw_file.rb +4 -0
  36. data/lib/action_view/test_case.rb +50 -53
  37. data/lib/action_view.rb +4 -0
  38. metadata +12 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cc81c16e4d502ce1736e2ff17c85dbb50ed6209d6ded187af4f846d05540f551
4
- data.tar.gz: faa7c34dff4cfc391389c56b52afd0cbbbdbaf5ee7805ae3e1d1fd78940f1195
3
+ metadata.gz: 625c1e6b4e3cc45ecce5dafa0697614d9ac34d31bd582f53c46620b60ff323a1
4
+ data.tar.gz: 5aec58970306776aa8ffcc3738a2e8b8ebb0b266777946341601b8bf38c6ff47
5
5
  SHA512:
6
- metadata.gz: 1e9c0c527c580719aea26c3a8499d1b1b82e4da5074271403c0060d0d96b604e23fe953ae8ede37d901ba7830fd3700a82297be2d29d574845eb79b559277d0f
7
- data.tar.gz: 24a3fc73c41d00476204519044e278f8c545db961ac02e88d810325f6cc7d831d410e203e1691767b1cca6672c0ab2d0c5b19179276c47a672b8489827d0545d
6
+ metadata.gz: e4e7e64f11986f77cf38942336bb217309275e4548fc6082f306551b25dc2b1bb016d50d85cb84619976e026696eba83796ca763aff8d86ac5b1009333b404ce
7
+ data.tar.gz: 397cf668c2a7dbd78e93ac4765c8adbbe6d245ea3c704b840297cae38b51779997be6caf62855b1ba3fb16e8a84180ff85fd6079ea8253809fe810521d5d8fac
data/CHANGELOG.md CHANGED
@@ -1,9 +1,40 @@
1
- ## Rails 8.0.2 (March 12, 2025) ##
1
+ ## Rails 8.1.0.beta1 (September 04, 2025) ##
2
2
 
3
- * No changes.
3
+ * Allow `current_page?` to match against specific HTTP method(s) with a `method:` option.
4
4
 
5
+ *Ben Sheldon*
5
6
 
6
- ## Rails 8.0.2 (March 12, 2025) ##
7
+ * remove `autocomplete="off"` on hidden inputs generated by `form_tag`, `token_tag`, `method_tag`, and the hidden
8
+ parameter fields included in `button_to` forms will omit the `autocomplete="off"` attribute.
9
+
10
+ *nkulway*
11
+
12
+ * Enable configuring the strategy for tracking dependencies between Action
13
+ View templates.
14
+
15
+ The existing `:regex` strategy is kept as the default, but with
16
+ `load_defaults 8.1` the strategy will be `:ruby` (using a real Ruby parser).
17
+
18
+ *Hartley McGuire*
19
+
20
+ * Introduce `relative_time_in_words` helper
21
+
22
+ ```ruby
23
+ relative_time_in_words(3.minutes.from_now) # => "in 3 minutes"
24
+ relative_time_in_words(3.minutes.ago) # => "3 minutes ago"
25
+ relative_time_in_words(10.seconds.ago, include_seconds: true) # => "less than 10 seconds ago"
26
+ ```
27
+
28
+ *Matheus Richard*
29
+
30
+ * Make `nonce: false` remove the nonce attribute from `javascript_tag`, `javascript_include_tag`, and `stylesheet_link_tag`.
31
+
32
+ *francktrouillez*
33
+
34
+ * Add `dom_target` helper to create `dom_id`-like strings from an unlimited
35
+ number of objects.
36
+
37
+ *Ben Sheldon*
7
38
 
8
39
  * Respect `html_options[:form]` when `collection_checkboxes` generates the
9
40
  hidden `<input>`.
@@ -34,11 +65,10 @@
34
65
 
35
66
  *Mike Dalessio*
36
67
 
37
- * Fix stack overflow error in dependency tracker when dealing with circular dependencies
68
+ * Improve error highlighting of multi-line methods in ERB templates or
69
+ templates where the error occurs within a do-end block.
38
70
 
39
- *Jean Boussier*
40
-
41
- ## Rails 8.0.1 (December 13, 2024) ##
71
+ *Martin Emde*
42
72
 
43
73
  * Fix a crash in ERB template error highlighting when the error occurs on a
44
74
  line in the compiled template that is past the end of the source template.
@@ -51,57 +81,12 @@
51
81
 
52
82
  *Martin Emde*
53
83
 
84
+ * Allow `hidden_field` and `hidden_field_tag` to accept a custom autocomplete value.
54
85
 
55
- ## Rails 8.0.0.1 (December 10, 2024) ##
56
-
57
- * No changes.
58
-
59
-
60
- ## Rails 8.0.0 (November 07, 2024) ##
61
-
62
- * No changes.
63
-
64
-
65
- ## Rails 8.0.0.rc2 (October 30, 2024) ##
66
-
67
- * No changes.
68
-
69
-
70
- ## Rails 8.0.0.rc1 (October 19, 2024) ##
71
-
72
- * Remove deprecated support to passing a content to void tag elements on the `tag` builder.
73
-
74
- *Rafael Mendonça França*
75
-
76
- * Remove deprecated support to passing `nil` to the `model:` argument of `form_with`.
77
-
78
- *Rafael Mendonça França*
79
-
80
-
81
- ## Rails 8.0.0.beta1 (September 26, 2024) ##
82
-
83
- * Enable DependencyTracker to evaluate renders with trailing interpolation.
84
-
85
- ```erb
86
- <%= render "maintenance_tasks/runs/info/#{run.status}" %>
87
- ```
88
-
89
- Previously, the DependencyTracker would ignore this render, but now it will
90
- mark all partials in the "maintenance_tasks/runs/info" folder as
91
- dependencies.
92
-
93
- *Hartley McGuire*
94
-
95
- * Rename `text_area` methods into `textarea`
96
-
97
- Old names are still available as aliases.
98
-
99
- *Sean Doyle*
100
-
101
- * Rename `check_box*` methods into `checkbox*`.
86
+ *brendon*
102
87
 
103
- Old names are still available as aliases.
88
+ * Add a new configuration `content_security_policy_nonce_auto` for automatically adding a nonce to the tags affected by the directives specified by the `content_security_policy_nonce_directives` configuration option.
104
89
 
105
- *Jean Boussier*
90
+ *francktrouillez*
106
91
 
107
- Please check [7-2-stable](https://github.com/rails/rails/blob/7-2-stable/actionview/CHANGELOG.md) for previous changes.
92
+ Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/actionview/CHANGELOG.md) for previous changes.
data/README.rdoc CHANGED
@@ -35,6 +35,6 @@ Bug reports for the Ruby on \Rails project can be filed here:
35
35
 
36
36
  * https://github.com/rails/rails/issues
37
37
 
38
- Feature requests should be discussed on the rails-core mailing list here:
38
+ Feature requests should be discussed on the rubyonrails-core forum here:
39
39
 
40
40
  * https://discuss.rubyonrails.org/c/rubyonrails-core
@@ -181,6 +181,10 @@ module ActionView # :nodoc:
181
181
  class_attribute :_routes
182
182
  class_attribute :logger
183
183
 
184
+ # Specify whether to omit autocomplete="off" on hidden inputs generated by helpers.
185
+ # Configured via `config.action_view.remove_hidden_field_autocomplete`
186
+ cattr_accessor :remove_hidden_field_autocomplete, default: false
187
+
184
188
  class << self
185
189
  delegate :erb_trim_mode=, to: "ActionView::Template::Handlers::ERB"
186
190
 
@@ -242,8 +246,6 @@ module ActionView # :nodoc:
242
246
  # :startdoc:
243
247
 
244
248
  def initialize(lookup_context, assigns, controller) # :nodoc:
245
- @_config = ActiveSupport::InheritableOptions.new
246
-
247
249
  @lookup_context = lookup_context
248
250
 
249
251
  @view_renderer = ActionView::Renderer.new @lookup_context
@@ -45,7 +45,7 @@ module ActionView
45
45
  @raw_buffer << if value.html_safe?
46
46
  value
47
47
  else
48
- CGI.escapeHTML(value)
48
+ ERB::Util.unwrapped_html_escape(value)
49
49
  end
50
50
  end
51
51
  self
@@ -91,7 +91,7 @@ module ActionView
91
91
 
92
92
  def render_dependencies
93
93
  dependencies = []
94
- render_calls = source.split(/\brender\b/).drop(1)
94
+ render_calls = source.scan(/<%(?:(?:(?!<%).)*?\brender\b((?:(?!%>).)*?))%>/m).flatten
95
95
 
96
96
  render_calls.each do |arguments|
97
97
  add_dependencies(dependencies, arguments, LAYOUT_DEPENDENCY)
@@ -36,6 +36,11 @@ module ActionView
36
36
  @trackers.delete(handler)
37
37
  end
38
38
 
39
- register_tracker :erb, ERBTracker
39
+ case ActionView.render_tracker
40
+ when :ruby
41
+ register_tracker :erb, RubyTracker
42
+ else
43
+ register_tracker :erb, ERBTracker
44
+ end
40
45
  end
41
46
  end
@@ -8,9 +8,9 @@ module ActionView
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 8
11
- MINOR = 0
12
- TINY = 2
13
- PRE = nil
11
+ MINOR = 1
12
+ TINY = 0
13
+ PRE = "beta1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -26,6 +26,8 @@ module ActionView
26
26
  mattr_accessor :image_decoding
27
27
  mattr_accessor :preload_links_header
28
28
  mattr_accessor :apply_stylesheet_media_default
29
+ mattr_accessor :auto_include_nonce_for_scripts
30
+ mattr_accessor :auto_include_nonce_for_styles
29
31
 
30
32
  # Returns an HTML script tag for each of the +sources+ provided.
31
33
  #
@@ -115,7 +117,7 @@ module ActionView
115
117
  path_options = options.extract!("protocol", "extname", "host", "skip_pipeline").symbolize_keys
116
118
  preload_links = []
117
119
  use_preload_links_header = options["preload_links_header"].nil? ? preload_links_header : options.delete("preload_links_header")
118
- nopush = options["nopush"].nil? ? true : options.delete("nopush")
120
+ nopush = options["nopush"].nil? || options.delete("nopush")
119
121
  crossorigin = options.delete("crossorigin")
120
122
  crossorigin = "anonymous" if crossorigin == true
121
123
  integrity = options["integrity"]
@@ -127,6 +129,7 @@ module ActionView
127
129
  preload_link = "<#{href}>; rel=#{rel}; as=script"
128
130
  preload_link += "; crossorigin=#{crossorigin}" unless crossorigin.nil?
129
131
  preload_link += "; integrity=#{integrity}" unless integrity.nil?
132
+ preload_link += "; nonce=#{content_security_policy_nonce}" if options["nonce"] == true
130
133
  preload_link += "; nopush" if nopush
131
134
  preload_links << preload_link
132
135
  end
@@ -134,8 +137,10 @@ module ActionView
134
137
  "src" => href,
135
138
  "crossorigin" => crossorigin
136
139
  }.merge!(options)
137
- if tag_options["nonce"] == true
140
+ if tag_options["nonce"] == true || (!tag_options.key?("nonce") && auto_include_nonce_for_scripts)
138
141
  tag_options["nonce"] = content_security_policy_nonce
142
+ elsif tag_options["nonce"] == false
143
+ tag_options.delete("nonce")
139
144
  end
140
145
  content_tag("script", "", tag_options)
141
146
  }.join("\n").html_safe
@@ -206,7 +211,7 @@ module ActionView
206
211
  preload_links = []
207
212
  crossorigin = options.delete("crossorigin")
208
213
  crossorigin = "anonymous" if crossorigin == true
209
- nopush = options["nopush"].nil? ? true : options.delete("nopush")
214
+ nopush = options["nopush"].nil? || options.delete("nopush")
210
215
  integrity = options["integrity"]
211
216
 
212
217
  sources_tags = sources.uniq.map { |source|
@@ -215,6 +220,7 @@ module ActionView
215
220
  preload_link = "<#{href}>; rel=preload; as=style"
216
221
  preload_link += "; crossorigin=#{crossorigin}" unless crossorigin.nil?
217
222
  preload_link += "; integrity=#{integrity}" unless integrity.nil?
223
+ preload_link += "; nonce=#{content_security_policy_nonce}" if options["nonce"] == true
218
224
  preload_link += "; nopush" if nopush
219
225
  preload_links << preload_link
220
226
  end
@@ -223,8 +229,10 @@ module ActionView
223
229
  "crossorigin" => crossorigin,
224
230
  "href" => href
225
231
  }.merge!(options)
226
- if tag_options["nonce"] == true
232
+ if tag_options["nonce"] == true || (!tag_options.key?("nonce") && auto_include_nonce_for_styles)
227
233
  tag_options["nonce"] = content_security_policy_nonce
234
+ elsif tag_options["nonce"] == false
235
+ tag_options.delete("nonce")
228
236
  end
229
237
 
230
238
  if apply_stylesheet_media_default && tag_options["media"].blank?
@@ -362,6 +370,13 @@ module ActionView
362
370
  integrity = options[:integrity]
363
371
  nopush = options.delete(:nopush) || false
364
372
  rel = mime_type == "module" ? "modulepreload" : "preload"
373
+ add_nonce = content_security_policy_nonce &&
374
+ respond_to?(:request) &&
375
+ request.content_security_policy_nonce_directives&.include?("#{as_type}-src")
376
+
377
+ if add_nonce
378
+ options[:nonce] = content_security_policy_nonce
379
+ end
365
380
 
366
381
  link_tag = tag.link(
367
382
  rel: rel,
@@ -375,6 +390,7 @@ module ActionView
375
390
  preload_link += "; type=#{mime_type}" if mime_type
376
391
  preload_link += "; crossorigin=#{crossorigin}" if crossorigin
377
392
  preload_link += "; integrity=#{integrity}" if integrity
393
+ preload_link += "; nonce=#{content_security_policy_nonce}" if add_nonce
378
394
  preload_link += "; nopush" if nopush
379
395
 
380
396
  send_preload_links_header([preload_link])
@@ -170,7 +170,7 @@ module ActionView
170
170
 
171
171
  # Creates an entry tag for a specific record and prefills the id using class and id.
172
172
  #
173
- # Options:
173
+ # ==== Options
174
174
  #
175
175
  # * <tt>:published</tt>: Time first published. Defaults to the created_at attribute on the record if one such exists.
176
176
  # * <tt>:updated</tt>: Time of update. Defaults to the updated_at attribute on the record if one such exists.
@@ -44,10 +44,10 @@ module ActionView
44
44
  #
45
45
  # @greeting # => "Welcome to my shiny new web page! The date and time is 2018-09-06 11:09:16 -0500"
46
46
  #
47
- def capture(*args, &block)
47
+ def capture(*, **, &block)
48
48
  value = nil
49
49
  @output_buffer ||= ActionView::OutputBuffer.new
50
- buffer = @output_buffer.capture { value = yield(*args) }
50
+ buffer = @output_buffer.capture { value = yield(*, **) }
51
51
 
52
52
  string = if @output_buffer.equal?(value)
53
53
  buffer
@@ -20,11 +20,15 @@ module ActionView
20
20
  def assign_controller(controller)
21
21
  if @_controller = controller
22
22
  @_request = controller.request if controller.respond_to?(:request)
23
- @_config = controller.config.inheritable_copy if controller.respond_to?(:config)
23
+ if controller.respond_to?(:config)
24
+ @_config = controller.config.inheritable_copy
25
+ else
26
+ @_config = ActiveSupport::InheritableOptions.new
27
+ end
24
28
  @_default_form_builder = controller.default_form_builder if controller.respond_to?(:default_form_builder)
25
29
  else
26
30
  @_request ||= nil
27
- @_config ||= nil
31
+ @_config = ActiveSupport::InheritableOptions.new
28
32
  @_default_form_builder ||= nil
29
33
  end
30
34
  end
@@ -136,8 +136,15 @@ module ActionView
136
136
  from_year += 1 if from_time.month >= 3
137
137
  to_year = to_time.year
138
138
  to_year -= 1 if to_time.month < 3
139
- leap_years = (from_year > to_year) ? 0 : (from_year..to_year).count { |x| Date.leap?(x) }
139
+
140
+ leap_years = if from_year > to_year
141
+ 0
142
+ else
143
+ fyear = from_year - 1
144
+ (to_year / 4 - to_year / 100 + to_year / 400) - (fyear / 4 - fyear / 100 + fyear / 400)
145
+ end
140
146
  minute_offset_for_leap_year = leap_years * 1440
147
+
141
148
  # Discount the leap year days when calculating year distance.
142
149
  # e.g. if there are 20 leap year days between 2 dates having the same day
143
150
  # and month then based on 365 days calculation
@@ -179,6 +186,23 @@ module ActionView
179
186
 
180
187
  alias_method :distance_of_time_in_words_to_now, :time_ago_in_words
181
188
 
189
+ # Like <tt>time_ago_in_words</tt>, but adds a prefix/suffix depending on whether the time is in the past or future.
190
+ # You can use the <tt>scope</tt> option to customize the translation scope. All other options
191
+ # are forwarded to <tt>time_ago_in_words</tt>.
192
+ #
193
+ # relative_time_in_words(3.minutes.from_now) # => "in 3 minutes"
194
+ # relative_time_in_words(3.minutes.ago) # => "3 minutes ago"
195
+ # relative_time_in_words(10.seconds.ago, include_seconds: true) # => "less than 10 seconds ago"
196
+ #
197
+ # See also #time_ago_in_words
198
+ def relative_time_in_words(from_time, options = {})
199
+ now = Time.now
200
+ time = distance_of_time_in_words(from_time, now, options.except(:scope))
201
+ key = from_time > now ? :future : :past
202
+
203
+ I18n.t(key, time: time, scope: options.fetch(:scope, :'datetime.relative'), locale: options[:locale])
204
+ end
205
+
182
206
  # Returns a set of select tags (one for year, month, and day) pre-selected for accessing a specified date-based
183
207
  # attribute (identified by +method+) on an object assigned to the template (identified by +object+).
184
208
  #
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cgi"
4
3
  require "action_view/helpers/date_helper"
5
4
  require "action_view/helpers/url_helper"
6
5
  require "action_view/helpers/form_tag_helper"
@@ -1632,7 +1631,8 @@ module ActionView
1632
1631
  #
1633
1632
  # A +FormBuilder+ object is associated with a particular model object and
1634
1633
  # allows you to generate fields associated with the model object. The
1635
- # +FormBuilder+ object is yielded when using #form_with or #fields_for.
1634
+ # +FormBuilder+ object is yielded when using
1635
+ # {form_with}[rdof-ref:ActionView::Helpers::FormHelper#form_with] or #fields_for.
1636
1636
  # For example:
1637
1637
  #
1638
1638
  # <%= form_with model: @person do |person_form| %>
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cgi"
4
3
  require "erb"
5
4
  require "active_support/core_ext/string/output_safety"
6
5
  require "active_support/core_ext/array/extract_options"
@@ -13,7 +12,7 @@ module ActionView
13
12
  #
14
13
  # Provides a number of methods for turning different kinds of containers into a set of option tags.
15
14
  #
16
- # The <tt>collection_select</tt>, <tt>select</tt> and <tt>time_zone_select</tt> methods take an <tt>options</tt> parameter, a hash:
15
+ # The #collection_select, #select and #time_zone_select methods take an <tt>options</tt> parameter, a hash:
17
16
  #
18
17
  # * <tt>:include_blank</tt> - set to true or a prompt string if the first option element of the select element is a blank. Useful if there is not a default value required for the select element.
19
18
  #
@@ -55,7 +54,7 @@ module ActionView
55
54
  # <option value="3">Rafael</option>
56
55
  # </select>
57
56
  #
58
- # * <tt>:index</tt> - like the other form helpers, <tt>select</tt> can accept an <tt>:index</tt> option to manually set the ID used in the resulting output. Unlike other helpers, <tt>select</tt> expects this
57
+ # * <tt>:index</tt> - like the other form helpers, #select can accept an <tt>:index</tt> option to manually set the ID used in the resulting output. Unlike other helpers, #select expects this
59
58
  # option to be in the +html_options+ parameter.
60
59
  #
61
60
  # select("album[]", :genre, %w[ rap rock country ], {}, { index: nil })
@@ -80,7 +79,7 @@ module ActionView
80
79
  # <option disabled="disabled" value="restricted">restricted</option>
81
80
  # </select>
82
81
  #
83
- # When used with the <tt>collection_select</tt> helper, <tt>:disabled</tt> can also be a Proc that identifies those options that should be disabled.
82
+ # When used with the #collection_select helper, <tt>:disabled</tt> can also be a Proc that identifies those options that should be disabled.
84
83
  #
85
84
  # collection_select(:post, :category_id, Category.all, :id, :name, { disabled: -> (category) { category.archived? } })
86
85
  #
@@ -105,7 +104,7 @@ module ActionView
105
104
  #
106
105
  # Example with <tt>@post.person_id => 2</tt>:
107
106
  #
108
- # select :post, :person_id, Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: true })
107
+ # select :post, :person_id, Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: true }
109
108
  #
110
109
  # would become:
111
110
  #
@@ -126,7 +125,7 @@ module ActionView
126
125
  # or <tt>selected: nil</tt> to leave all options unselected. Similarly, you can specify values to be disabled in the option
127
126
  # tags by specifying the <tt>:disabled</tt> option. This can either be a single value or an array of values to be disabled.
128
127
  #
129
- # A block can be passed to +select+ to customize how the options tags will be rendered. This
128
+ # A block can be passed to #select to customize how the options tags will be rendered. This
130
129
  # is useful when the options tag has complex attributes.
131
130
  #
132
131
  # select(report, :campaign_ids) do
@@ -265,7 +264,7 @@ module ActionView
265
264
  # In addition to the <tt>:include_blank</tt> option documented above,
266
265
  # this method also supports a <tt>:model</tt> option, which defaults
267
266
  # to ActiveSupport::TimeZone. This may be used by users to specify a
268
- # different time zone model object. (See +time_zone_options_for_select+
267
+ # different time zone model object. (See #time_zone_options_for_select
269
268
  # for more information.)
270
269
  #
271
270
  # You can also supply an array of ActiveSupport::TimeZone objects
@@ -294,7 +293,7 @@ module ActionView
294
293
  end
295
294
 
296
295
  # Returns select and option tags for the given object and method, using
297
- # <tt>weekday_options_for_select</tt> to generate the list of option tags.
296
+ # #weekday_options_for_select to generate the list of option tags.
298
297
  def weekday_select(object, method, options = {}, html_options = {}, &block)
299
298
  Tags::WeekdaySelect.new(object, method, self, options, html_options, &block).render
300
299
  end
@@ -370,7 +369,7 @@ module ActionView
370
369
  html_attributes[:disabled] ||= disabled && option_value_selected?(value, disabled)
371
370
  html_attributes[:value] = value
372
371
 
373
- tag_builder.content_tag_string(:option, text, html_attributes)
372
+ tag_builder.option(text, **html_attributes)
374
373
  end.join("\n").html_safe
375
374
  end
376
375
 
@@ -411,7 +410,7 @@ module ActionView
411
410
  options_for_select(options, select_deselect)
412
411
  end
413
412
 
414
- # Returns a string of <tt><option></tt> tags, like <tt>options_from_collection_for_select</tt>, but
413
+ # Returns a string of <tt><option></tt> tags, like #options_from_collection_for_select, but
415
414
  # groups them by <tt><optgroup></tt> tags based on the object relationships of the arguments.
416
415
  #
417
416
  # Parameters:
@@ -468,7 +467,7 @@ module ActionView
468
467
  end.join.html_safe
469
468
  end
470
469
 
471
- # Returns a string of <tt><option></tt> tags, like <tt>options_for_select</tt>, but
470
+ # Returns a string of <tt><option></tt> tags, like #options_for_select, but
472
471
  # wraps them with <tt><optgroup></tt> tags:
473
472
  #
474
473
  # grouped_options = [
@@ -496,7 +495,8 @@ module ActionView
496
495
  # <option value="France">France</option>
497
496
  # </optgroup>
498
497
  #
499
- # Parameters:
498
+ # ==== Parameters
499
+ #
500
500
  # * +grouped_options+ - Accepts a nested array or hash of strings. The first value serves as the
501
501
  # <tt><optgroup></tt> label while the second value must be an array of options. The second value can be a
502
502
  # nested array of text-value pairs. See <tt>options_for_select</tt> for more info.
@@ -507,7 +507,8 @@ module ActionView
507
507
  # which will have the +selected+ attribute set. Note: It is possible for this value to match multiple options
508
508
  # as you might have the same option in multiple groups. Each will then get <tt>selected="selected"</tt>.
509
509
  #
510
- # Options:
510
+ # ==== Options
511
+ #
511
512
  # * <tt>:prompt</tt> - set to true or a prompt string. When the select element doesn't have a value yet, this
512
513
  # prepends an option with a generic prompt - "Please select" - or the given prompt string.
513
514
  # * <tt>:divider</tt> - the divider for the options groups.
@@ -599,7 +600,8 @@ module ActionView
599
600
 
600
601
  # Returns a string of option tags for the days of the week.
601
602
  #
602
- # Options:
603
+ # ====Options
604
+ #
603
605
  # * <tt>:index_as_value</tt> - Defaults to false, set to true to use the indexes from
604
606
  # <tt>I18n.translate("date.day_names")</tt> as the values. By default, Sunday is always 0.
605
607
  # * <tt>:day_format</tt> - The I18n key of the array to use for the weekday options.
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cgi"
4
3
  require "action_view/helpers/content_exfiltration_prevention_helper"
5
4
  require "action_view/helpers/url_helper"
6
5
  require "action_view/helpers/text_helper"
@@ -306,7 +305,11 @@ module ActionView
306
305
  # # => <input type="hidden" name="collected_input" id="collected_input"
307
306
  # value="" onchange="alert(&#39;Input collected!&#39;)" autocomplete="off" />
308
307
  def hidden_field_tag(name, value = nil, options = {})
309
- text_field_tag(name, value, options.merge(type: :hidden, autocomplete: "off"))
308
+ html_options = options.merge(type: :hidden)
309
+ unless ActionView::Base.remove_hidden_field_autocomplete
310
+ html_options[:autocomplete] = "off" unless html_options.key?(:autocomplete)
311
+ end
312
+ text_field_tag(name, value, html_options)
310
313
  end
311
314
 
312
315
  # Creates a file upload field. If you are using file uploads then you will also need
@@ -976,10 +979,15 @@ module ActionView
976
979
  # Creates the hidden UTF-8 enforcer tag. Override this method in a helper
977
980
  # to customize the tag.
978
981
  def utf8_enforcer_tag
979
- # Use raw HTML to ensure the value is written as an HTML entity; it
980
- # needs to be the right character regardless of which encoding the
981
- # browser infers.
982
- '<input name="utf8" type="hidden" value="&#x2713;" autocomplete="off" />'.html_safe
982
+ options = {
983
+ type: "hidden",
984
+ name: "utf8",
985
+ value: "&#x2713;".html_safe
986
+ }
987
+
988
+ options[:autocomplete] = "off" unless ActionView::Base.remove_hidden_field_autocomplete
989
+
990
+ tag(:input, options)
983
991
  end
984
992
 
985
993
  private
@@ -1047,9 +1055,9 @@ module ActionView
1047
1055
  end
1048
1056
 
1049
1057
  def form_tag_with_body(html_options, content)
1050
- output = form_tag_html(html_options)
1051
- output << content.to_s if content
1052
- output.safe_concat("</form>")
1058
+ extra_tags = extra_tags_for_form(html_options)
1059
+ html = content_tag(:form, safe_join([extra_tags, content]), html_options)
1060
+ prevent_content_exfiltration(html)
1053
1061
  end
1054
1062
 
1055
1063
  # see http://www.w3.org/TR/html4/types.html#type-name
@@ -4,6 +4,8 @@ module ActionView
4
4
  module Helpers # :nodoc:
5
5
  # = Action View JavaScript \Helpers
6
6
  module JavaScriptHelper
7
+ mattr_accessor :auto_include_nonce
8
+
7
9
  JS_ESCAPE_MAP = {
8
10
  "\\" => "\\\\",
9
11
  "</" => '<\/',
@@ -81,8 +83,10 @@ module ActionView
81
83
  content_or_options_with_block
82
84
  end
83
85
 
84
- if html_options[:nonce] == true
86
+ if html_options[:nonce] == true || (!html_options.key?(:nonce) && auto_include_nonce)
85
87
  html_options[:nonce] = content_security_policy_nonce
88
+ elsif html_options[:nonce] == false
89
+ html_options.delete(:nonce)
86
90
  end
87
91
 
88
92
  content_tag("script", javascript_cdata_section(content), html_options)
@@ -26,6 +26,8 @@ module ActionView
26
26
 
27
27
  # Delegates to ActiveSupport::NumberHelper#number_to_phone.
28
28
  #
29
+ # number_to_phone("1234567890") # => "123-456-7890"
30
+ #
29
31
  # Additionally, supports a +:raise+ option that will cause
30
32
  # InvalidNumberError to be raised if +number+ is not a valid number:
31
33
  #
@@ -42,6 +44,8 @@ module ActionView
42
44
 
43
45
  # Delegates to ActiveSupport::NumberHelper#number_to_currency.
44
46
  #
47
+ # number_to_currency("1234") # => "$1234.00"
48
+ #
45
49
  # Additionally, supports a +:raise+ option that will cause
46
50
  # InvalidNumberError to be raised if +number+ is not a valid number:
47
51
  #
@@ -54,6 +58,8 @@ module ActionView
54
58
 
55
59
  # Delegates to ActiveSupport::NumberHelper#number_to_percentage.
56
60
  #
61
+ # number_to_percentage("99") # => "99.000%"
62
+ #
57
63
  # Additionally, supports a +:raise+ option that will cause
58
64
  # InvalidNumberError to be raised if +number+ is not a valid number:
59
65
  #
@@ -66,6 +72,8 @@ module ActionView
66
72
 
67
73
  # Delegates to ActiveSupport::NumberHelper#number_to_delimited.
68
74
  #
75
+ # number_with_delimiter("1234") # => "1,234"
76
+ #
69
77
  # Additionally, supports a +:raise+ option that will cause
70
78
  # InvalidNumberError to be raised if +number+ is not a valid number:
71
79
  #
@@ -78,6 +86,8 @@ module ActionView
78
86
 
79
87
  # Delegates to ActiveSupport::NumberHelper#number_to_rounded.
80
88
  #
89
+ # number_with_precision("1234") # => "1234.000"
90
+ #
81
91
  # Additionally, supports a +:raise+ option that will cause
82
92
  # InvalidNumberError to be raised if +number+ is not a valid number:
83
93
  #
@@ -90,6 +100,8 @@ module ActionView
90
100
 
91
101
  # Delegates to ActiveSupport::NumberHelper#number_to_human_size.
92
102
  #
103
+ # number_to_human_size("1234") # => "1.21 KB"
104
+ #
93
105
  # Additionally, supports a +:raise+ option that will cause
94
106
  # InvalidNumberError to be raised if +number+ is not a valid number:
95
107
  #
@@ -102,6 +114,8 @@ module ActionView
102
114
 
103
115
  # Delegates to ActiveSupport::NumberHelper#number_to_human.
104
116
  #
117
+ # number_to_human("1234") # => "1.23 Thousand"
118
+ #
105
119
  # Additionally, supports a +:raise+ option that will cause
106
120
  # InvalidNumberError to be raised if +number+ is not a valid number:
107
121
  #