actionview 4.2.11.1 → 6.1.5

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

Potentially problematic release.


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

Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +232 -186
  3. data/MIT-LICENSE +1 -2
  4. data/README.rdoc +9 -8
  5. data/lib/action_view/base.rb +115 -39
  6. data/lib/action_view/buffers.rb +18 -1
  7. data/lib/action_view/cache_expiry.rb +52 -0
  8. data/lib/action_view/context.rb +8 -12
  9. data/lib/action_view/dependency_tracker.rb +61 -21
  10. data/lib/action_view/digestor.rb +89 -85
  11. data/lib/action_view/flows.rb +11 -12
  12. data/lib/action_view/gem_version.rb +6 -4
  13. data/lib/action_view/helpers/active_model_helper.rb +16 -11
  14. data/lib/action_view/helpers/asset_tag_helper.rb +282 -83
  15. data/lib/action_view/helpers/asset_url_helper.rb +175 -69
  16. data/lib/action_view/helpers/atom_feed_helper.rb +20 -17
  17. data/lib/action_view/helpers/cache_helper.rb +107 -43
  18. data/lib/action_view/helpers/capture_helper.rb +20 -13
  19. data/lib/action_view/helpers/controller_helper.rb +15 -4
  20. data/lib/action_view/helpers/csp_helper.rb +26 -0
  21. data/lib/action_view/helpers/csrf_helper.rb +8 -6
  22. data/lib/action_view/helpers/date_helper.rb +232 -130
  23. data/lib/action_view/helpers/debug_helper.rb +7 -6
  24. data/lib/action_view/helpers/form_helper.rb +808 -146
  25. data/lib/action_view/helpers/form_options_helper.rb +124 -78
  26. data/lib/action_view/helpers/form_tag_helper.rb +120 -74
  27. data/lib/action_view/helpers/javascript_helper.rb +33 -17
  28. data/lib/action_view/helpers/number_helper.rb +87 -62
  29. data/lib/action_view/helpers/output_safety_helper.rb +36 -4
  30. data/lib/action_view/helpers/rendering_helper.rb +21 -10
  31. data/lib/action_view/helpers/sanitize_helper.rb +30 -31
  32. data/lib/action_view/helpers/tag_helper.rb +269 -68
  33. data/lib/action_view/helpers/tags/base.rb +141 -97
  34. data/lib/action_view/helpers/tags/check_box.rb +20 -19
  35. data/lib/action_view/helpers/tags/checkable.rb +4 -2
  36. data/lib/action_view/helpers/tags/collection_check_boxes.rb +12 -34
  37. data/lib/action_view/helpers/tags/collection_helpers.rb +69 -36
  38. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +6 -12
  39. data/lib/action_view/helpers/tags/collection_select.rb +4 -2
  40. data/lib/action_view/helpers/tags/color_field.rb +4 -3
  41. data/lib/action_view/helpers/tags/date_field.rb +3 -2
  42. data/lib/action_view/helpers/tags/date_select.rb +38 -37
  43. data/lib/action_view/helpers/tags/datetime_field.rb +4 -3
  44. data/lib/action_view/helpers/tags/datetime_local_field.rb +3 -2
  45. data/lib/action_view/helpers/tags/datetime_select.rb +2 -0
  46. data/lib/action_view/helpers/tags/email_field.rb +2 -0
  47. data/lib/action_view/helpers/tags/file_field.rb +2 -0
  48. data/lib/action_view/helpers/tags/grouped_collection_select.rb +4 -2
  49. data/lib/action_view/helpers/tags/hidden_field.rb +6 -0
  50. data/lib/action_view/helpers/tags/label.rb +7 -2
  51. data/lib/action_view/helpers/tags/month_field.rb +3 -2
  52. data/lib/action_view/helpers/tags/number_field.rb +2 -0
  53. data/lib/action_view/helpers/tags/password_field.rb +3 -1
  54. data/lib/action_view/helpers/tags/placeholderable.rb +3 -1
  55. data/lib/action_view/helpers/tags/radio_button.rb +7 -6
  56. data/lib/action_view/helpers/tags/range_field.rb +2 -0
  57. data/lib/action_view/helpers/tags/search_field.rb +14 -9
  58. data/lib/action_view/helpers/tags/select.rb +11 -10
  59. data/lib/action_view/helpers/tags/tel_field.rb +2 -0
  60. data/lib/action_view/helpers/tags/text_area.rb +4 -2
  61. data/lib/action_view/helpers/tags/text_field.rb +8 -8
  62. data/lib/action_view/helpers/tags/time_field.rb +3 -2
  63. data/lib/action_view/helpers/tags/time_select.rb +2 -0
  64. data/lib/action_view/helpers/tags/time_zone_select.rb +3 -1
  65. data/lib/action_view/helpers/tags/translator.rb +15 -16
  66. data/lib/action_view/helpers/tags/url_field.rb +2 -0
  67. data/lib/action_view/helpers/tags/week_field.rb +3 -2
  68. data/lib/action_view/helpers/tags.rb +3 -1
  69. data/lib/action_view/helpers/text_helper.rb +56 -38
  70. data/lib/action_view/helpers/translation_helper.rb +150 -68
  71. data/lib/action_view/helpers/url_helper.rb +284 -117
  72. data/lib/action_view/helpers.rb +5 -3
  73. data/lib/action_view/layouts.rb +68 -63
  74. data/lib/action_view/log_subscriber.rb +77 -10
  75. data/lib/action_view/lookup_context.rb +134 -91
  76. data/lib/action_view/model_naming.rb +3 -1
  77. data/lib/action_view/path_set.rb +26 -24
  78. data/lib/action_view/railtie.rb +62 -13
  79. data/lib/action_view/record_identifier.rb +53 -26
  80. data/lib/action_view/renderer/abstract_renderer.rb +151 -14
  81. data/lib/action_view/renderer/collection_renderer.rb +196 -0
  82. data/lib/action_view/renderer/object_renderer.rb +34 -0
  83. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +102 -0
  84. data/lib/action_view/renderer/partial_renderer.rb +55 -303
  85. data/lib/action_view/renderer/renderer.rb +66 -9
  86. data/lib/action_view/renderer/streaming_template_renderer.rb +58 -54
  87. data/lib/action_view/renderer/template_renderer.rb +82 -73
  88. data/lib/action_view/rendering.rb +71 -45
  89. data/lib/action_view/routing_url_for.rb +34 -23
  90. data/lib/action_view/tasks/cache_digests.rake +25 -0
  91. data/lib/action_view/template/error.rb +44 -29
  92. data/lib/action_view/template/handlers/builder.rb +12 -13
  93. data/lib/action_view/template/handlers/erb/erubi.rb +89 -0
  94. data/lib/action_view/template/handlers/erb.rb +23 -89
  95. data/lib/action_view/template/handlers/html.rb +11 -0
  96. data/lib/action_view/template/handlers/raw.rb +4 -4
  97. data/lib/action_view/template/handlers.rb +12 -8
  98. data/lib/action_view/template/html.rb +10 -11
  99. data/lib/action_view/template/inline.rb +22 -0
  100. data/lib/action_view/template/raw_file.rb +25 -0
  101. data/lib/action_view/template/renderable.rb +24 -0
  102. data/lib/action_view/template/resolver.rb +263 -197
  103. data/lib/action_view/template/sources/file.rb +17 -0
  104. data/lib/action_view/template/sources.rb +13 -0
  105. data/lib/action_view/template/text.rb +8 -10
  106. data/lib/action_view/template/types.rb +18 -18
  107. data/lib/action_view/template.rb +108 -92
  108. data/lib/action_view/test_case.rb +66 -53
  109. data/lib/action_view/testing/resolvers.rb +24 -33
  110. data/lib/action_view/unbound_template.rb +31 -0
  111. data/lib/action_view/version.rb +3 -1
  112. data/lib/action_view/view_paths.rb +73 -58
  113. data/lib/action_view.rb +14 -8
  114. data/lib/assets/compiled/rails-ujs.js +746 -0
  115. metadata +42 -29
  116. data/lib/action_view/helpers/record_tag_helper.rb +0 -108
  117. data/lib/action_view/tasks/dependencies.rake +0 -23
@@ -1,11 +1,14 @@
1
- require 'cgi'
2
- require 'action_view/helpers/tag_helper'
3
- require 'active_support/core_ext/string/output_safety'
4
- require 'active_support/core_ext/module/attribute_accessors'
1
+ # frozen_string_literal: true
2
+
3
+ require "cgi"
4
+ require "action_view/helpers/tag_helper"
5
+ require "active_support/core_ext/string/output_safety"
6
+ require "active_support/core_ext/module/attribute_accessors"
7
+ require "active_support/core_ext/symbol/starts_ends_with"
5
8
 
6
9
  module ActionView
7
10
  # = Action View Form Tag Helpers
8
- module Helpers
11
+ module Helpers #:nodoc:
9
12
  # Provides a number of methods for creating form tags that don't rely on an Active Record object assigned to the template like
10
13
  # FormHelper does. Instead, you provide the names and values manually.
11
14
  #
@@ -18,9 +21,11 @@ module ActionView
18
21
  include TextHelper
19
22
 
20
23
  mattr_accessor :embed_authenticity_token_in_remote_forms
21
- self.embed_authenticity_token_in_remote_forms = false
24
+ self.embed_authenticity_token_in_remote_forms = nil
25
+
26
+ mattr_accessor :default_enforce_utf8, default: true
22
27
 
23
- # Starts a form tag that points the action to an url configured with <tt>url_for_options</tt> just like
28
+ # Starts a form tag that points the action to a URL configured with <tt>url_for_options</tt> just like
24
29
  # ActionController::Base#url_for. The method for the form defaults to POST.
25
30
  #
26
31
  # ==== Options
@@ -80,7 +85,7 @@ module ActionView
80
85
  # associated records. <tt>option_tags</tt> is a string containing the option tags for the select box.
81
86
  #
82
87
  # ==== Options
83
- # * <tt>:multiple</tt> - If set to true the selection will allow multiple choices.
88
+ # * <tt>:multiple</tt> - If set to true, the selection will allow multiple choices.
84
89
  # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
85
90
  # * <tt>:include_blank</tt> - If set to true, an empty option will be created. If set to a string, the string will be used as the option's content and the value will be empty.
86
91
  # * <tt>:prompt</tt> - Create a prompt option with blank value and the text asking user to select something.
@@ -93,27 +98,27 @@ module ActionView
93
98
  # select_tag "people", options_from_collection_for_select(@people, "id", "name", "1")
94
99
  # # <select id="people" name="people"><option value="1" selected="selected">David</option></select>
95
100
  #
96
- # select_tag "people", "<option>David</option>".html_safe
101
+ # select_tag "people", raw("<option>David</option>")
97
102
  # # => <select id="people" name="people"><option>David</option></select>
98
103
  #
99
- # select_tag "count", "<option>1</option><option>2</option><option>3</option><option>4</option>".html_safe
104
+ # select_tag "count", raw("<option>1</option><option>2</option><option>3</option><option>4</option>")
100
105
  # # => <select id="count" name="count"><option>1</option><option>2</option>
101
106
  # # <option>3</option><option>4</option></select>
102
107
  #
103
- # select_tag "colors", "<option>Red</option><option>Green</option><option>Blue</option>".html_safe, multiple: true
108
+ # select_tag "colors", raw("<option>Red</option><option>Green</option><option>Blue</option>"), multiple: true
104
109
  # # => <select id="colors" multiple="multiple" name="colors[]"><option>Red</option>
105
110
  # # <option>Green</option><option>Blue</option></select>
106
111
  #
107
- # select_tag "locations", "<option>Home</option><option selected='selected'>Work</option><option>Out</option>".html_safe
112
+ # select_tag "locations", raw("<option>Home</option><option selected='selected'>Work</option><option>Out</option>")
108
113
  # # => <select id="locations" name="locations"><option>Home</option><option selected='selected'>Work</option>
109
114
  # # <option>Out</option></select>
110
115
  #
111
- # select_tag "access", "<option>Read</option><option>Write</option>".html_safe, multiple: true, class: 'form_input', id: 'unique_id'
116
+ # select_tag "access", raw("<option>Read</option><option>Write</option>"), multiple: true, class: 'form_input', id: 'unique_id'
112
117
  # # => <select class="form_input" id="unique_id" multiple="multiple" name="access[]"><option>Read</option>
113
118
  # # <option>Write</option></select>
114
119
  #
115
120
  # select_tag "people", options_from_collection_for_select(@people, "id", "name"), include_blank: true
116
- # # => <select id="people" name="people"><option value=""></option><option value="1">David</option></select>
121
+ # # => <select id="people" name="people"><option value="" label=" "></option><option value="1">David</option></select>
117
122
  #
118
123
  # select_tag "people", options_from_collection_for_select(@people, "id", "name"), include_blank: "All"
119
124
  # # => <select id="people" name="people"><option value="">All</option><option value="1">David</option></select>
@@ -121,7 +126,7 @@ module ActionView
121
126
  # select_tag "people", options_from_collection_for_select(@people, "id", "name"), prompt: "Select something"
122
127
  # # => <select id="people" name="people"><option value="">Select something</option><option value="1">David</option></select>
123
128
  #
124
- # select_tag "destination", "<option>NYC</option><option>Paris</option><option>Rome</option>".html_safe, disabled: true
129
+ # select_tag "destination", raw("<option>NYC</option><option>Paris</option><option>Rome</option>"), disabled: true
125
130
  # # => <select disabled="disabled" id="destination" name="destination"><option>NYC</option>
126
131
  # # <option>Paris</option><option>Rome</option></select>
127
132
  #
@@ -130,25 +135,28 @@ module ActionView
130
135
  # # <option selected="selected">MasterCard</option></select>
131
136
  def select_tag(name, option_tags = nil, options = {})
132
137
  option_tags ||= ""
133
- html_name = (options[:multiple] == true && !name.to_s.ends_with?("[]")) ? "#{name}[]" : name
138
+ html_name = (options[:multiple] == true && !name.end_with?("[]")) ? "#{name}[]" : name
134
139
 
135
140
  if options.include?(:include_blank)
136
- include_blank = options.delete(:include_blank)
141
+ include_blank = options[:include_blank]
142
+ options = options.except(:include_blank)
143
+ options_for_blank_options_tag = { value: "" }
137
144
 
138
145
  if include_blank == true
139
- include_blank = ''
146
+ include_blank = ""
147
+ options_for_blank_options_tag[:label] = " "
140
148
  end
141
149
 
142
150
  if include_blank
143
- option_tags = content_tag(:option, include_blank, value: '').safe_concat(option_tags)
151
+ option_tags = content_tag("option", include_blank, options_for_blank_options_tag).safe_concat(option_tags)
144
152
  end
145
153
  end
146
154
 
147
155
  if prompt = options.delete(:prompt)
148
- option_tags = content_tag(:option, prompt, value: '').safe_concat(option_tags)
156
+ option_tags = content_tag("option", prompt, value: "").safe_concat(option_tags)
149
157
  end
150
158
 
151
- content_tag :select, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
159
+ content_tag "select", option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
152
160
  end
153
161
 
154
162
  # Creates a standard text field; use these text fields to input smaller chunks of text like a username
@@ -159,6 +167,8 @@ module ActionView
159
167
  # * <tt>:size</tt> - The number of visible characters that will fit in the input.
160
168
  # * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
161
169
  # * <tt>:placeholder</tt> - The text contained in the field by default which is removed when the field receives focus.
170
+ # If set to true, use a translation is found in the current I18n locale
171
+ # (through helpers.placeholders.<modelname>.<attribute>).
162
172
  # * Any other key creates standard HTML attributes for the tag.
163
173
  #
164
174
  # ==== Examples
@@ -231,7 +241,7 @@ module ActionView
231
241
  # # => <input id="collected_input" name="collected_input" onchange="alert('Input collected!')"
232
242
  # # type="hidden" value="" />
233
243
  def hidden_field_tag(name, value = nil, options = {})
234
- text_field_tag(name, value, options.merge(type: :hidden))
244
+ text_field_tag(name, value, options.merge(type: :hidden, autocomplete: "off"))
235
245
  end
236
246
 
237
247
  # Creates a file upload field. If you are using file uploads then you will also need
@@ -270,7 +280,7 @@ module ActionView
270
280
  # file_field_tag 'file', accept: 'text/html', class: 'upload', value: 'index.html'
271
281
  # # => <input accept="text/html" class="upload" id="file" name="file" type="file" value="index.html" />
272
282
  def file_field_tag(name, options = {})
273
- text_field_tag(name, nil, options.merge(type: :file))
283
+ text_field_tag(name, nil, convert_direct_upload_option_to_url(options.merge(type: :file)))
274
284
  end
275
285
 
276
286
  # Creates a password field, a masked text field that will hide the users input behind a mask character.
@@ -383,14 +393,14 @@ module ActionView
383
393
  # * Any other key creates standard HTML options for the tag.
384
394
  #
385
395
  # ==== Examples
386
- # radio_button_tag 'gender', 'male'
387
- # # => <input id="gender_male" name="gender" type="radio" value="male" />
396
+ # radio_button_tag 'favorite_color', 'maroon'
397
+ # # => <input id="favorite_color_maroon" name="favorite_color" type="radio" value="maroon" />
388
398
  #
389
399
  # radio_button_tag 'receive_updates', 'no', true
390
400
  # # => <input checked="checked" id="receive_updates_no" name="receive_updates" type="radio" value="no" />
391
401
  #
392
402
  # radio_button_tag 'time_slot', "3:00 p.m.", false, disabled: true
393
- # # => <input disabled="disabled" id="time_slot_300_pm" name="time_slot" type="radio" value="3:00 p.m." />
403
+ # # => <input disabled="disabled" id="time_slot_3:00_p.m." name="time_slot" type="radio" value="3:00 p.m." />
394
404
  #
395
405
  # radio_button_tag 'color', "green", true, class: "color_input"
396
406
  # # => <input checked="checked" class="color_input" id="color_green" name="color" type="radio" value="green" />
@@ -414,42 +424,45 @@ module ActionView
414
424
  # the form is processed normally, otherwise no action is taken.
415
425
  # * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a
416
426
  # disabled version of the submit button when the form is submitted. This feature is
417
- # provided by the unobtrusive JavaScript driver.
427
+ # provided by the unobtrusive JavaScript driver. To disable this feature for a single submit tag
428
+ # pass <tt>:data => { disable_with: false }</tt> Defaults to value attribute.
418
429
  #
419
430
  # ==== Examples
420
431
  # submit_tag
421
- # # => <input name="commit" type="submit" value="Save changes" />
432
+ # # => <input name="commit" data-disable-with="Save changes" type="submit" value="Save changes" />
422
433
  #
423
434
  # submit_tag "Edit this article"
424
- # # => <input name="commit" type="submit" value="Edit this article" />
435
+ # # => <input name="commit" data-disable-with="Edit this article" type="submit" value="Edit this article" />
425
436
  #
426
437
  # submit_tag "Save edits", disabled: true
427
- # # => <input disabled="disabled" name="commit" type="submit" value="Save edits" />
438
+ # # => <input disabled="disabled" name="commit" data-disable-with="Save edits" type="submit" value="Save edits" />
428
439
  #
429
- # submit_tag "Complete sale", data: { disable_with: "Please wait..." }
430
- # # => <input name="commit" data-disable-with="Please wait..." type="submit" value="Complete sale" />
440
+ # submit_tag "Complete sale", data: { disable_with: "Submitting..." }
441
+ # # => <input name="commit" data-disable-with="Submitting..." type="submit" value="Complete sale" />
431
442
  #
432
443
  # submit_tag nil, class: "form_submit"
433
444
  # # => <input class="form_submit" name="commit" type="submit" />
434
445
  #
435
446
  # submit_tag "Edit", class: "edit_button"
436
- # # => <input class="edit_button" name="commit" type="submit" value="Edit" />
447
+ # # => <input class="edit_button" data-disable-with="Edit" name="commit" type="submit" value="Edit" />
437
448
  #
438
449
  # submit_tag "Save", data: { confirm: "Are you sure?" }
439
- # # => <input name='commit' type='submit' value='Save' data-confirm="Are you sure?" />
450
+ # # => <input name='commit' type='submit' value='Save' data-disable-with="Save" data-confirm="Are you sure?" />
440
451
  #
441
452
  def submit_tag(value = "Save changes", options = {})
442
- options = options.stringify_keys
443
-
444
- tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options)
453
+ options = options.deep_stringify_keys
454
+ tag_options = { "type" => "submit", "name" => "commit", "value" => value }.update(options)
455
+ set_default_disable_with value, tag_options
456
+ tag :input, tag_options
445
457
  end
446
458
 
447
459
  # Creates a button element that defines a <tt>submit</tt> button,
448
- # <tt>reset</tt>button or a generic button which can be used in
460
+ # <tt>reset</tt> button or a generic button which can be used in
449
461
  # JavaScript, for example. You can use the button tag as a regular
450
462
  # submit tag but it isn't supported in legacy browsers. However,
451
- # the button tag allows richer labels such as images and emphasis,
452
- # so this helper will also accept a block.
463
+ # the button tag does allow for richer labels such as images and emphasis,
464
+ # so this helper will also accept a block. By default, it will create
465
+ # a button tag with type <tt>submit</tt>, if type is not given.
453
466
  #
454
467
  # ==== Options
455
468
  # * <tt>:data</tt> - This option can be used to add custom data attributes.
@@ -472,6 +485,15 @@ module ActionView
472
485
  # button_tag
473
486
  # # => <button name="button" type="submit">Button</button>
474
487
  #
488
+ # button_tag 'Reset', type: 'reset'
489
+ # # => <button name="button" type="reset">Reset</button>
490
+ #
491
+ # button_tag 'Button', type: 'button'
492
+ # # => <button name="button" type="button">Button</button>
493
+ #
494
+ # button_tag 'Reset', type: 'reset', disabled: true
495
+ # # => <button name="button" type="reset" disabled="disabled">Reset</button>
496
+ #
475
497
  # button_tag(type: 'button') do
476
498
  # content_tag(:strong, 'Ask me!')
477
499
  # end
@@ -479,6 +501,9 @@ module ActionView
479
501
  # # <strong>Ask me!</strong>
480
502
  # # </button>
481
503
  #
504
+ # button_tag "Save", data: { confirm: "Are you sure?" }
505
+ # # => <button name="button" type="submit" data-confirm="Are you sure?">Save</button>
506
+ #
482
507
  # button_tag "Checkout", data: { disable_with: "Please wait..." }
483
508
  # # => <button data-disable-with="Please wait..." name="button" type="submit">Checkout</button>
484
509
  #
@@ -489,12 +514,12 @@ module ActionView
489
514
  options ||= {}
490
515
  end
491
516
 
492
- options = { 'name' => 'button', 'type' => 'submit' }.merge!(options.stringify_keys)
517
+ options = { "name" => "button", "type" => "submit" }.merge!(options.stringify_keys)
493
518
 
494
519
  if block_given?
495
520
  content_tag :button, options, &block
496
521
  else
497
- content_tag :button, content_or_options || 'Button', options
522
+ content_tag :button, content_or_options || "Button", options
498
523
  end
499
524
  end
500
525
 
@@ -515,22 +540,23 @@ module ActionView
515
540
  #
516
541
  # ==== Examples
517
542
  # image_submit_tag("login.png")
518
- # # => <input alt="Login" src="/assets/login.png" type="image" />
543
+ # # => <input src="/assets/login.png" type="image" />
519
544
  #
520
545
  # image_submit_tag("purchase.png", disabled: true)
521
- # # => <input alt="Purchase" disabled="disabled" src="/assets/purchase.png" type="image" />
546
+ # # => <input disabled="disabled" src="/assets/purchase.png" type="image" />
522
547
  #
523
548
  # image_submit_tag("search.png", class: 'search_button', alt: 'Find')
524
- # # => <input alt="Find" class="search_button" src="/assets/search.png" type="image" />
549
+ # # => <input class="search_button" src="/assets/search.png" type="image" />
525
550
  #
526
551
  # image_submit_tag("agree.png", disabled: true, class: "agree_disagree_button")
527
- # # => <input alt="Agree" class="agree_disagree_button" disabled="disabled" src="/assets/agree.png" type="image" />
552
+ # # => <input class="agree_disagree_button" disabled="disabled" src="/assets/agree.png" type="image" />
528
553
  #
529
554
  # image_submit_tag("save.png", data: { confirm: "Are you sure?" })
530
- # # => <input alt="Save" src="/assets/save.png" data-confirm="Are you sure?" type="image" />
555
+ # # => <input src="/assets/save.png" data-confirm="Are you sure?" type="image" />
531
556
  def image_submit_tag(source, options = {})
532
557
  options = options.stringify_keys
533
- tag :input, { "alt" => image_alt(source), "type" => "image", "src" => path_to_image(source) }.update(options)
558
+ src = path_to_image(source, skip_pipeline: options.delete("skip_pipeline"))
559
+ tag :input, { "type" => "image", "src" => src }.update(options)
534
560
  end
535
561
 
536
562
  # Creates a field set for grouping HTML form elements.
@@ -555,7 +581,7 @@ module ActionView
555
581
  # # => <fieldset class="format"><p><input id="name" name="name" type="text" /></p></fieldset>
556
582
  def field_set_tag(legend = nil, options = nil, &block)
557
583
  output = tag(:fieldset, options, true)
558
- output.safe_concat(content_tag(:legend, legend)) unless legend.blank?
584
+ output.safe_concat(content_tag("legend", legend)) unless legend.blank?
559
585
  output.concat(capture(&block)) if block_given?
560
586
  output.safe_concat("</fieldset>")
561
587
  end
@@ -656,7 +682,7 @@ module ActionView
656
682
  text_field_tag(name, value, options.merge(type: :time))
657
683
  end
658
684
 
659
- # Creates a text field of type "datetime".
685
+ # Creates a text field of type "datetime-local".
660
686
  #
661
687
  # === Options
662
688
  # * <tt>:min</tt> - The minimum acceptable value.
@@ -664,19 +690,10 @@ module ActionView
664
690
  # * <tt>:step</tt> - The acceptable value granularity.
665
691
  # * Otherwise accepts the same options as text_field_tag.
666
692
  def datetime_field_tag(name, value = nil, options = {})
667
- text_field_tag(name, value, options.merge(type: :datetime))
693
+ text_field_tag(name, value, options.merge(type: "datetime-local"))
668
694
  end
669
695
 
670
- # Creates a text field of type "datetime-local".
671
- #
672
- # === Options
673
- # * <tt>:min</tt> - The minimum acceptable value.
674
- # * <tt>:max</tt> - The maximum acceptable value.
675
- # * <tt>:step</tt> - The acceptable value granularity.
676
- # * Otherwise accepts the same options as text_field_tag.
677
- def datetime_local_field_tag(name, value = nil, options = {})
678
- text_field_tag(name, value, options.merge(type: 'datetime-local'))
679
- end
696
+ alias datetime_local_field_tag datetime_field_tag
680
697
 
681
698
  # Creates a text field of type "month".
682
699
  #
@@ -776,10 +793,10 @@ module ActionView
776
793
  # # => <input id="quantity" name="quantity" min="1" max="9" type="number" />
777
794
  #
778
795
  # number_field_tag 'quantity', nil, min: 1, max: 10
779
- # # => <input id="quantity" name="quantity" min="1" max="9" type="number" />
796
+ # # => <input id="quantity" name="quantity" min="1" max="10" type="number" />
780
797
  #
781
798
  # number_field_tag 'quantity', nil, min: 1, max: 10, step: 2
782
- # # => <input id="quantity" name="quantity" min="1" max="9" step="2" type="number" />
799
+ # # => <input id="quantity" name="quantity" min="1" max="10" step="2" type="number" />
783
800
  #
784
801
  # number_field_tag 'quantity', '1', class: 'special_input', disabled: true
785
802
  # # => <input disabled="disabled" class="special_input" id="quantity" name="quantity" type="number" value="1" />
@@ -806,7 +823,7 @@ module ActionView
806
823
  # Use raw HTML to ensure the value is written as an HTML entity; it
807
824
  # needs to be the right character regardless of which encoding the
808
825
  # browser infers.
809
- '<input name="utf8" type="hidden" value="&#x2713;" />'.html_safe
826
+ '<input name="utf8" type="hidden" value="&#x2713;" autocomplete="off" />'.html_safe
810
827
  end
811
828
 
812
829
  private
@@ -835,21 +852,28 @@ module ActionView
835
852
 
836
853
  def extra_tags_for_form(html_options)
837
854
  authenticity_token = html_options.delete("authenticity_token")
838
- method = html_options.delete("method").to_s
855
+ method = html_options.delete("method").to_s.downcase
839
856
 
840
- method_tag = case method
841
- when /^get$/i # must be case-insensitive, but can't use downcase as might be nil
857
+ method_tag = \
858
+ case method
859
+ when "get"
842
860
  html_options["method"] = "get"
843
- ''
844
- when /^post$/i, "", nil
861
+ ""
862
+ when "post", ""
845
863
  html_options["method"] = "post"
846
- token_tag(authenticity_token)
864
+ token_tag(authenticity_token, form_options: {
865
+ action: html_options["action"],
866
+ method: "post"
867
+ })
847
868
  else
848
869
  html_options["method"] = "post"
849
- method_tag(method) + token_tag(authenticity_token)
850
- end
870
+ method_tag(method) + token_tag(authenticity_token, form_options: {
871
+ action: html_options["action"],
872
+ method: method
873
+ })
874
+ end
851
875
 
852
- if html_options.delete("enforce_utf8") { true }
876
+ if html_options.delete("enforce_utf8") { default_enforce_utf8 }
853
877
  utf8_enforcer_tag + method_tag
854
878
  else
855
879
  method_tag
@@ -869,7 +893,29 @@ module ActionView
869
893
 
870
894
  # see http://www.w3.org/TR/html4/types.html#type-name
871
895
  def sanitize_to_id(name)
872
- name.to_s.delete(']').tr('^-a-zA-Z0-9:.', "_")
896
+ name.to_s.delete("]").tr("^-a-zA-Z0-9:.", "_")
897
+ end
898
+
899
+ def set_default_disable_with(value, tag_options)
900
+ data = tag_options.fetch("data", {})
901
+
902
+ if tag_options["data-disable-with"] == false || data["disable_with"] == false
903
+ data.delete("disable_with")
904
+ elsif ActionView::Base.automatically_disable_submit_tag
905
+ disable_with_text = tag_options["data-disable-with"]
906
+ disable_with_text ||= data["disable_with"]
907
+ disable_with_text ||= value.to_s.clone
908
+ tag_options.deep_merge!("data" => { "disable_with" => disable_with_text })
909
+ end
910
+
911
+ tag_options.delete("data-disable-with")
912
+ end
913
+
914
+ def convert_direct_upload_option_to_url(options)
915
+ if options.delete(:direct_upload) && respond_to?(:rails_direct_uploads_url)
916
+ options["data-direct-upload-url"] = rails_direct_uploads_url
917
+ end
918
+ options
873
919
  end
874
920
  end
875
921
  end
@@ -1,34 +1,39 @@
1
- require 'action_view/helpers/tag_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "action_view/helpers/tag_helper"
2
4
 
3
5
  module ActionView
4
- module Helpers
6
+ module Helpers #:nodoc:
5
7
  module JavaScriptHelper
6
8
  JS_ESCAPE_MAP = {
7
9
  '\\' => '\\\\',
8
- '</' => '<\/',
10
+ "</" => '<\/',
9
11
  "\r\n" => '\n',
10
12
  "\n" => '\n',
11
13
  "\r" => '\n',
12
14
  '"' => '\\"',
13
- "'" => "\\'"
15
+ "'" => "\\'",
16
+ "`" => "\\`",
17
+ "$" => "\\$"
14
18
  }
15
19
 
16
- JS_ESCAPE_MAP["\342\200\250".force_encoding(Encoding::UTF_8).encode!] = '&#x2028;'
17
- JS_ESCAPE_MAP["\342\200\251".force_encoding(Encoding::UTF_8).encode!] = '&#x2029;'
20
+ JS_ESCAPE_MAP[(+"\342\200\250").force_encoding(Encoding::UTF_8).encode!] = "&#x2028;"
21
+ JS_ESCAPE_MAP[(+"\342\200\251").force_encoding(Encoding::UTF_8).encode!] = "&#x2029;"
18
22
 
19
23
  # Escapes carriage returns and single and double quotes for JavaScript segments.
20
24
  #
21
25
  # Also available through the alias j(). This is particularly helpful in JavaScript
22
26
  # responses, like:
23
27
  #
24
- # $('some_element').replaceWith('<%=j render 'some/element_template' %>');
28
+ # $('some_element').replaceWith('<%= j render 'some/element_template' %>');
25
29
  def escape_javascript(javascript)
26
- if javascript
27
- result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|\342\200\251|[\n\r"'])/u) {|match| JS_ESCAPE_MAP[match] }
28
- javascript.html_safe? ? result.html_safe : result
30
+ javascript = javascript.to_s
31
+ if javascript.empty?
32
+ result = ""
29
33
  else
30
- ''
34
+ result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|\342\200\251|[\n\r"']|[`]|[$])/u, JS_ESCAPE_MAP)
31
35
  end
36
+ javascript.html_safe? ? result.html_safe : result
32
37
  end
33
38
 
34
39
  alias_method :j, :escape_javascript
@@ -46,10 +51,10 @@ module ActionView
46
51
  # +html_options+ may be a hash of attributes for the <tt>\<script></tt>
47
52
  # tag.
48
53
  #
49
- # javascript_tag "alert('All is good')", defer: 'defer'
50
- #
51
- # Returns:
52
- # <script defer="defer">
54
+ # javascript_tag "alert('All is good')", type: 'application/javascript'
55
+ #
56
+ # Returns:
57
+ # <script type="application/javascript">
53
58
  # //<![CDATA[
54
59
  # alert('All is good')
55
60
  # //]]>
@@ -58,7 +63,14 @@ module ActionView
58
63
  # Instead of passing the content as an argument, you can also use a block
59
64
  # in which case, you pass your +html_options+ as the first parameter.
60
65
  #
61
- # <%= javascript_tag defer: 'defer' do -%>
66
+ # <%= javascript_tag type: 'application/javascript' do -%>
67
+ # alert('All is good')
68
+ # <% end -%>
69
+ #
70
+ # If you have a content security policy enabled then you can add an automatic
71
+ # nonce value by passing <tt>nonce: true</tt> as part of +html_options+. Example:
72
+ #
73
+ # <%= javascript_tag nonce: true do -%>
62
74
  # alert('All is good')
63
75
  # <% end -%>
64
76
  def javascript_tag(content_or_options_with_block = nil, html_options = {}, &block)
@@ -70,7 +82,11 @@ module ActionView
70
82
  content_or_options_with_block
71
83
  end
72
84
 
73
- content_tag(:script, javascript_cdata_section(content), html_options)
85
+ if html_options[:nonce] == true
86
+ html_options[:nonce] = content_security_policy_nonce
87
+ end
88
+
89
+ content_tag("script", javascript_cdata_section(content), html_options)
74
90
  end
75
91
 
76
92
  def javascript_cdata_section(content) #:nodoc: