actionview 8.0.3 → 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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -69
  3. data/lib/action_view/base.rb +4 -2
  4. data/lib/action_view/buffers.rb +1 -1
  5. data/lib/action_view/dependency_tracker/erb_tracker.rb +1 -1
  6. data/lib/action_view/dependency_tracker.rb +6 -1
  7. data/lib/action_view/gem_version.rb +3 -3
  8. data/lib/action_view/helpers/asset_tag_helper.rb +22 -6
  9. data/lib/action_view/helpers/capture_helper.rb +2 -2
  10. data/lib/action_view/helpers/controller_helper.rb +6 -2
  11. data/lib/action_view/helpers/date_helper.rb +17 -0
  12. data/lib/action_view/helpers/form_helper.rb +2 -3
  13. data/lib/action_view/helpers/form_options_helper.rb +10 -12
  14. data/lib/action_view/helpers/form_tag_helper.rb +17 -10
  15. data/lib/action_view/helpers/javascript_helper.rb +5 -1
  16. data/lib/action_view/helpers/number_helper.rb +14 -0
  17. data/lib/action_view/helpers/tag_helper.rb +31 -34
  18. data/lib/action_view/helpers/tags/base.rb +9 -9
  19. data/lib/action_view/helpers/tags/check_box.rb +2 -2
  20. data/lib/action_view/helpers/tags/datetime_field.rb +1 -1
  21. data/lib/action_view/helpers/tags/file_field.rb +1 -1
  22. data/lib/action_view/helpers/tags/hidden_field.rb +1 -1
  23. data/lib/action_view/helpers/tags/label.rb +10 -3
  24. data/lib/action_view/helpers/tags/radio_button.rb +1 -1
  25. data/lib/action_view/helpers/tags/select.rb +6 -1
  26. data/lib/action_view/helpers/tags/select_renderer.rb +3 -3
  27. data/lib/action_view/helpers/tags/text_area.rb +1 -1
  28. data/lib/action_view/helpers/tags/text_field.rb +1 -1
  29. data/lib/action_view/helpers/translation_helper.rb +6 -1
  30. data/lib/action_view/helpers/url_helper.rb +37 -9
  31. data/lib/action_view/locale/en.yml +3 -0
  32. data/lib/action_view/railtie.rb +11 -0
  33. data/lib/action_view/record_identifier.rb +21 -0
  34. data/lib/action_view/renderer/partial_renderer.rb +16 -0
  35. data/lib/action_view/template/error.rb +7 -3
  36. data/lib/action_view/template/handlers/erb.rb +36 -11
  37. data/lib/action_view/test_case.rb +50 -52
  38. data/lib/action_view.rb +3 -0
  39. metadata +10 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d906f994cc2a7151f2763ccfd5505479b2ba0dd408797b28716d495b4ec89089
4
- data.tar.gz: 10cb316f59e90d20729c7f61ec92c0e3b6b28e359ea13b2692736e5ffbe7e7a4
3
+ metadata.gz: 625c1e6b4e3cc45ecce5dafa0697614d9ac34d31bd582f53c46620b60ff323a1
4
+ data.tar.gz: 5aec58970306776aa8ffcc3738a2e8b8ebb0b266777946341601b8bf38c6ff47
5
5
  SHA512:
6
- metadata.gz: a845f01c731db0f215c2a7d29888924fa1e50d3c68a17e1ed37e6dd746aa47a3250c7018d6d66639fc9ef7039f0b6d64234110edd310870bdae2074932044356
7
- data.tar.gz: be07fd924f900d3d8c537652678d941fed5ea46ff657197e2182fdbaf4554923a1f1c41e27873735911a85b7a4d5819c330b35ceacefa90ca542c04e9b6053a8
6
+ metadata.gz: e4e7e64f11986f77cf38942336bb217309275e4548fc6082f306551b25dc2b1bb016d50d85cb84619976e026696eba83796ca763aff8d86ac5b1009333b404ce
7
+ data.tar.gz: 397cf668c2a7dbd78e93ac4765c8adbbe6d245ea3c704b840297cae38b51779997be6caf62855b1ba3fb16e8a84180ff85fd6079ea8253809fe810521d5d8fac
data/CHANGELOG.md CHANGED
@@ -1,31 +1,40 @@
1
- ## Rails 8.0.3 (September 22, 2025) ##
1
+ ## Rails 8.1.0.beta1 (September 04, 2025) ##
2
2
 
3
- * Fix label with `for` option not getting prefixed by form `namespace` value
3
+ * Allow `current_page?` to match against specific HTTP method(s) with a `method:` option.
4
4
 
5
- *Abeid Ahmed*, *Hartley McGuire*
5
+ *Ben Sheldon*
6
6
 
7
- * Fix `javascript_include_tag` `type` option to accept either strings and symbols.
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.
8
9
 
9
- ```ruby
10
- javascript_include_tag "application", type: :module
11
- javascript_include_tag "application", type: "module"
12
- ```
10
+ *nkulway*
13
11
 
14
- Previously, only the string value was recognized.
12
+ * Enable configuring the strategy for tracking dependencies between Action
13
+ View templates.
15
14
 
16
- *Jean Boussier*
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
17
 
18
- * Fix `excerpt` helper with non-whitespace separator.
18
+ *Hartley McGuire*
19
19
 
20
- *Jonathan Hefner*
20
+ * Introduce `relative_time_in_words` helper
21
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
+ ```
22
27
 
23
- ## Rails 8.0.2.1 (August 13, 2025) ##
28
+ *Matheus Richard*
24
29
 
25
- * No changes.
30
+ * Make `nonce: false` remove the nonce attribute from `javascript_tag`, `javascript_include_tag`, and `stylesheet_link_tag`.
26
31
 
32
+ *francktrouillez*
27
33
 
28
- ## Rails 8.0.2 (March 12, 2025) ##
34
+ * Add `dom_target` helper to create `dom_id`-like strings from an unlimited
35
+ number of objects.
36
+
37
+ *Ben Sheldon*
29
38
 
30
39
  * Respect `html_options[:form]` when `collection_checkboxes` generates the
31
40
  hidden `<input>`.
@@ -56,11 +65,10 @@
56
65
 
57
66
  *Mike Dalessio*
58
67
 
59
- * Fix stack overflow error in dependency tracker when dealing with circular dependencies
60
-
61
- *Jean Boussier*
68
+ * Improve error highlighting of multi-line methods in ERB templates or
69
+ templates where the error occurs within a do-end block.
62
70
 
63
- ## Rails 8.0.1 (December 13, 2024) ##
71
+ *Martin Emde*
64
72
 
65
73
  * Fix a crash in ERB template error highlighting when the error occurs on a
66
74
  line in the compiled template that is past the end of the source template.
@@ -73,57 +81,12 @@
73
81
 
74
82
  *Martin Emde*
75
83
 
84
+ * Allow `hidden_field` and `hidden_field_tag` to accept a custom autocomplete value.
76
85
 
77
- ## Rails 8.0.0.1 (December 10, 2024) ##
78
-
79
- * No changes.
80
-
81
-
82
- ## Rails 8.0.0 (November 07, 2024) ##
83
-
84
- * No changes.
85
-
86
-
87
- ## Rails 8.0.0.rc2 (October 30, 2024) ##
88
-
89
- * No changes.
90
-
91
-
92
- ## Rails 8.0.0.rc1 (October 19, 2024) ##
93
-
94
- * Remove deprecated support to passing a content to void tag elements on the `tag` builder.
95
-
96
- *Rafael Mendonça França*
97
-
98
- * Remove deprecated support to passing `nil` to the `model:` argument of `form_with`.
99
-
100
- *Rafael Mendonça França*
101
-
102
-
103
- ## Rails 8.0.0.beta1 (September 26, 2024) ##
104
-
105
- * Enable DependencyTracker to evaluate renders with trailing interpolation.
106
-
107
- ```erb
108
- <%= render "maintenance_tasks/runs/info/#{run.status}" %>
109
- ```
110
-
111
- Previously, the DependencyTracker would ignore this render, but now it will
112
- mark all partials in the "maintenance_tasks/runs/info" folder as
113
- dependencies.
114
-
115
- *Hartley McGuire*
116
-
117
- * Rename `text_area` methods into `textarea`
118
-
119
- Old names are still available as aliases.
120
-
121
- *Sean Doyle*
122
-
123
- * Rename `check_box*` methods into `checkbox*`.
86
+ *brendon*
124
87
 
125
- 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.
126
89
 
127
- *Jean Boussier*
90
+ *francktrouillez*
128
91
 
129
- 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.
@@ -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 = 3
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,11 +117,11 @@ 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"]
122
- rel = options["type"] == "module" || options["type"] == :module ? "modulepreload" : "preload"
124
+ rel = options["type"] == "module" ? "modulepreload" : "preload"
123
125
 
124
126
  sources_tags = sources.uniq.map { |source|
125
127
  href = path_to_javascript(source, path_options)
@@ -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?
@@ -361,7 +369,14 @@ module ActionView
361
369
  crossorigin = "anonymous" if crossorigin == true || (crossorigin.blank? && as_type == "font")
362
370
  integrity = options[:integrity]
363
371
  nopush = options.delete(:nopush) || false
364
- rel = mime_type == "module" || mime_type == :module ? "modulepreload" : "preload"
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])
@@ -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
@@ -186,6 +186,23 @@ module ActionView
186
186
 
187
187
  alias_method :distance_of_time_in_words_to_now, :time_ago_in_words
188
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
+
189
206
  # Returns a set of select tags (one for year, month, and day) pre-selected for accessing a specified date-based
190
207
  # attribute (identified by +method+) on an object assigned to the template (identified by +object+).
191
208
  #
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cgi/escape"
4
- require "cgi/util" if RUBY_VERSION < "3.5"
5
3
  require "action_view/helpers/date_helper"
6
4
  require "action_view/helpers/url_helper"
7
5
  require "action_view/helpers/form_tag_helper"
@@ -1633,7 +1631,8 @@ module ActionView
1633
1631
  #
1634
1632
  # A +FormBuilder+ object is associated with a particular model object and
1635
1633
  # allows you to generate fields associated with the model object. The
1636
- # +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.
1637
1636
  # For example:
1638
1637
  #
1639
1638
  # <%= form_with model: @person do |person_form| %>
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cgi/escape"
4
- require "cgi/util" if RUBY_VERSION < "3.5"
5
3
  require "erb"
6
4
  require "active_support/core_ext/string/output_safety"
7
5
  require "active_support/core_ext/array/extract_options"
@@ -14,7 +12,7 @@ module ActionView
14
12
  #
15
13
  # Provides a number of methods for turning different kinds of containers into a set of option tags.
16
14
  #
17
- # 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:
18
16
  #
19
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.
20
18
  #
@@ -56,7 +54,7 @@ module ActionView
56
54
  # <option value="3">Rafael</option>
57
55
  # </select>
58
56
  #
59
- # * <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
60
58
  # option to be in the +html_options+ parameter.
61
59
  #
62
60
  # select("album[]", :genre, %w[ rap rock country ], {}, { index: nil })
@@ -81,7 +79,7 @@ module ActionView
81
79
  # <option disabled="disabled" value="restricted">restricted</option>
82
80
  # </select>
83
81
  #
84
- # 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.
85
83
  #
86
84
  # collection_select(:post, :category_id, Category.all, :id, :name, { disabled: -> (category) { category.archived? } })
87
85
  #
@@ -106,7 +104,7 @@ module ActionView
106
104
  #
107
105
  # Example with <tt>@post.person_id => 2</tt>:
108
106
  #
109
- # 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 }
110
108
  #
111
109
  # would become:
112
110
  #
@@ -127,7 +125,7 @@ module ActionView
127
125
  # or <tt>selected: nil</tt> to leave all options unselected. Similarly, you can specify values to be disabled in the option
128
126
  # tags by specifying the <tt>:disabled</tt> option. This can either be a single value or an array of values to be disabled.
129
127
  #
130
- # 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
131
129
  # is useful when the options tag has complex attributes.
132
130
  #
133
131
  # select(report, :campaign_ids) do
@@ -266,7 +264,7 @@ module ActionView
266
264
  # In addition to the <tt>:include_blank</tt> option documented above,
267
265
  # this method also supports a <tt>:model</tt> option, which defaults
268
266
  # to ActiveSupport::TimeZone. This may be used by users to specify a
269
- # different time zone model object. (See +time_zone_options_for_select+
267
+ # different time zone model object. (See #time_zone_options_for_select
270
268
  # for more information.)
271
269
  #
272
270
  # You can also supply an array of ActiveSupport::TimeZone objects
@@ -295,7 +293,7 @@ module ActionView
295
293
  end
296
294
 
297
295
  # Returns select and option tags for the given object and method, using
298
- # <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.
299
297
  def weekday_select(object, method, options = {}, html_options = {}, &block)
300
298
  Tags::WeekdaySelect.new(object, method, self, options, html_options, &block).render
301
299
  end
@@ -371,7 +369,7 @@ module ActionView
371
369
  html_attributes[:disabled] ||= disabled && option_value_selected?(value, disabled)
372
370
  html_attributes[:value] = value
373
371
 
374
- tag_builder.content_tag_string(:option, text, html_attributes)
372
+ tag_builder.option(text, **html_attributes)
375
373
  end.join("\n").html_safe
376
374
  end
377
375
 
@@ -412,7 +410,7 @@ module ActionView
412
410
  options_for_select(options, select_deselect)
413
411
  end
414
412
 
415
- # 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
416
414
  # groups them by <tt><optgroup></tt> tags based on the object relationships of the arguments.
417
415
  #
418
416
  # Parameters:
@@ -469,7 +467,7 @@ module ActionView
469
467
  end.join.html_safe
470
468
  end
471
469
 
472
- # 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
473
471
  # wraps them with <tt><optgroup></tt> tags:
474
472
  #
475
473
  # grouped_options = [
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cgi/escape"
4
- require "cgi/util" if RUBY_VERSION < "3.5"
5
3
  require "action_view/helpers/content_exfiltration_prevention_helper"
6
4
  require "action_view/helpers/url_helper"
7
5
  require "action_view/helpers/text_helper"
@@ -307,7 +305,11 @@ module ActionView
307
305
  # # => <input type="hidden" name="collected_input" id="collected_input"
308
306
  # value="" onchange="alert(&#39;Input collected!&#39;)" autocomplete="off" />
309
307
  def hidden_field_tag(name, value = nil, options = {})
310
- 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)
311
313
  end
312
314
 
313
315
  # Creates a file upload field. If you are using file uploads then you will also need
@@ -977,10 +979,15 @@ module ActionView
977
979
  # Creates the hidden UTF-8 enforcer tag. Override this method in a helper
978
980
  # to customize the tag.
979
981
  def utf8_enforcer_tag
980
- # Use raw HTML to ensure the value is written as an HTML entity; it
981
- # needs to be the right character regardless of which encoding the
982
- # browser infers.
983
- '<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)
984
991
  end
985
992
 
986
993
  private
@@ -1048,9 +1055,9 @@ module ActionView
1048
1055
  end
1049
1056
 
1050
1057
  def form_tag_with_body(html_options, content)
1051
- output = form_tag_html(html_options)
1052
- output << content.to_s if content
1053
- 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)
1054
1061
  end
1055
1062
 
1056
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
  #