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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +232 -186
- data/MIT-LICENSE +1 -2
- data/README.rdoc +9 -8
- data/lib/action_view/base.rb +115 -39
- data/lib/action_view/buffers.rb +18 -1
- data/lib/action_view/cache_expiry.rb +52 -0
- data/lib/action_view/context.rb +8 -12
- data/lib/action_view/dependency_tracker.rb +61 -21
- data/lib/action_view/digestor.rb +89 -85
- data/lib/action_view/flows.rb +11 -12
- data/lib/action_view/gem_version.rb +6 -4
- data/lib/action_view/helpers/active_model_helper.rb +16 -11
- data/lib/action_view/helpers/asset_tag_helper.rb +282 -83
- data/lib/action_view/helpers/asset_url_helper.rb +175 -69
- data/lib/action_view/helpers/atom_feed_helper.rb +20 -17
- data/lib/action_view/helpers/cache_helper.rb +107 -43
- data/lib/action_view/helpers/capture_helper.rb +20 -13
- data/lib/action_view/helpers/controller_helper.rb +15 -4
- data/lib/action_view/helpers/csp_helper.rb +26 -0
- data/lib/action_view/helpers/csrf_helper.rb +8 -6
- data/lib/action_view/helpers/date_helper.rb +232 -130
- data/lib/action_view/helpers/debug_helper.rb +7 -6
- data/lib/action_view/helpers/form_helper.rb +808 -146
- data/lib/action_view/helpers/form_options_helper.rb +124 -78
- data/lib/action_view/helpers/form_tag_helper.rb +120 -74
- data/lib/action_view/helpers/javascript_helper.rb +33 -17
- data/lib/action_view/helpers/number_helper.rb +87 -62
- data/lib/action_view/helpers/output_safety_helper.rb +36 -4
- data/lib/action_view/helpers/rendering_helper.rb +21 -10
- data/lib/action_view/helpers/sanitize_helper.rb +30 -31
- data/lib/action_view/helpers/tag_helper.rb +269 -68
- data/lib/action_view/helpers/tags/base.rb +141 -97
- data/lib/action_view/helpers/tags/check_box.rb +20 -19
- data/lib/action_view/helpers/tags/checkable.rb +4 -2
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +12 -34
- data/lib/action_view/helpers/tags/collection_helpers.rb +69 -36
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +6 -12
- data/lib/action_view/helpers/tags/collection_select.rb +4 -2
- data/lib/action_view/helpers/tags/color_field.rb +4 -3
- data/lib/action_view/helpers/tags/date_field.rb +3 -2
- data/lib/action_view/helpers/tags/date_select.rb +38 -37
- data/lib/action_view/helpers/tags/datetime_field.rb +4 -3
- data/lib/action_view/helpers/tags/datetime_local_field.rb +3 -2
- data/lib/action_view/helpers/tags/datetime_select.rb +2 -0
- data/lib/action_view/helpers/tags/email_field.rb +2 -0
- data/lib/action_view/helpers/tags/file_field.rb +2 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +4 -2
- data/lib/action_view/helpers/tags/hidden_field.rb +6 -0
- data/lib/action_view/helpers/tags/label.rb +7 -2
- data/lib/action_view/helpers/tags/month_field.rb +3 -2
- data/lib/action_view/helpers/tags/number_field.rb +2 -0
- data/lib/action_view/helpers/tags/password_field.rb +3 -1
- data/lib/action_view/helpers/tags/placeholderable.rb +3 -1
- data/lib/action_view/helpers/tags/radio_button.rb +7 -6
- data/lib/action_view/helpers/tags/range_field.rb +2 -0
- data/lib/action_view/helpers/tags/search_field.rb +14 -9
- data/lib/action_view/helpers/tags/select.rb +11 -10
- data/lib/action_view/helpers/tags/tel_field.rb +2 -0
- data/lib/action_view/helpers/tags/text_area.rb +4 -2
- data/lib/action_view/helpers/tags/text_field.rb +8 -8
- data/lib/action_view/helpers/tags/time_field.rb +3 -2
- data/lib/action_view/helpers/tags/time_select.rb +2 -0
- data/lib/action_view/helpers/tags/time_zone_select.rb +3 -1
- data/lib/action_view/helpers/tags/translator.rb +15 -16
- data/lib/action_view/helpers/tags/url_field.rb +2 -0
- data/lib/action_view/helpers/tags/week_field.rb +3 -2
- data/lib/action_view/helpers/tags.rb +3 -1
- data/lib/action_view/helpers/text_helper.rb +56 -38
- data/lib/action_view/helpers/translation_helper.rb +150 -68
- data/lib/action_view/helpers/url_helper.rb +284 -117
- data/lib/action_view/helpers.rb +5 -3
- data/lib/action_view/layouts.rb +68 -63
- data/lib/action_view/log_subscriber.rb +77 -10
- data/lib/action_view/lookup_context.rb +134 -91
- data/lib/action_view/model_naming.rb +3 -1
- data/lib/action_view/path_set.rb +26 -24
- data/lib/action_view/railtie.rb +62 -13
- data/lib/action_view/record_identifier.rb +53 -26
- data/lib/action_view/renderer/abstract_renderer.rb +151 -14
- data/lib/action_view/renderer/collection_renderer.rb +196 -0
- data/lib/action_view/renderer/object_renderer.rb +34 -0
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +102 -0
- data/lib/action_view/renderer/partial_renderer.rb +55 -303
- data/lib/action_view/renderer/renderer.rb +66 -9
- data/lib/action_view/renderer/streaming_template_renderer.rb +58 -54
- data/lib/action_view/renderer/template_renderer.rb +82 -73
- data/lib/action_view/rendering.rb +71 -45
- data/lib/action_view/routing_url_for.rb +34 -23
- data/lib/action_view/tasks/cache_digests.rake +25 -0
- data/lib/action_view/template/error.rb +44 -29
- data/lib/action_view/template/handlers/builder.rb +12 -13
- data/lib/action_view/template/handlers/erb/erubi.rb +89 -0
- data/lib/action_view/template/handlers/erb.rb +23 -89
- data/lib/action_view/template/handlers/html.rb +11 -0
- data/lib/action_view/template/handlers/raw.rb +4 -4
- data/lib/action_view/template/handlers.rb +12 -8
- data/lib/action_view/template/html.rb +10 -11
- data/lib/action_view/template/inline.rb +22 -0
- data/lib/action_view/template/raw_file.rb +25 -0
- data/lib/action_view/template/renderable.rb +24 -0
- data/lib/action_view/template/resolver.rb +263 -197
- data/lib/action_view/template/sources/file.rb +17 -0
- data/lib/action_view/template/sources.rb +13 -0
- data/lib/action_view/template/text.rb +8 -10
- data/lib/action_view/template/types.rb +18 -18
- data/lib/action_view/template.rb +108 -92
- data/lib/action_view/test_case.rb +66 -53
- data/lib/action_view/testing/resolvers.rb +24 -33
- data/lib/action_view/unbound_template.rb +31 -0
- data/lib/action_view/version.rb +3 -1
- data/lib/action_view/view_paths.rb +73 -58
- data/lib/action_view.rb +14 -8
- data/lib/assets/compiled/rails-ujs.js +746 -0
- metadata +42 -29
- data/lib/action_view/helpers/record_tag_helper.rb +0 -108
- data/lib/action_view/tasks/dependencies.rake +0 -23
@@ -1,11 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
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 =
|
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
|
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>"
|
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>"
|
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>"
|
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>"
|
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>"
|
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>"
|
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.
|
138
|
+
html_name = (options[:multiple] == true && !name.end_with?("[]")) ? "#{name}[]" : name
|
134
139
|
|
135
140
|
if options.include?(:include_blank)
|
136
|
-
include_blank = options
|
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(
|
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(
|
156
|
+
option_tags = content_tag("option", prompt, value: "").safe_concat(option_tags)
|
149
157
|
end
|
150
158
|
|
151
|
-
content_tag
|
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 '
|
387
|
-
# # => <input id="
|
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="
|
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: "
|
430
|
-
# # => <input name="commit" data-disable-with="
|
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.
|
443
|
-
|
444
|
-
|
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
|
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 = {
|
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 ||
|
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
|
543
|
+
# # => <input src="/assets/login.png" type="image" />
|
519
544
|
#
|
520
545
|
# image_submit_tag("purchase.png", disabled: true)
|
521
|
-
# # => <input
|
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
|
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
|
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
|
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
|
-
|
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(
|
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:
|
693
|
+
text_field_tag(name, value, options.merge(type: "datetime-local"))
|
668
694
|
end
|
669
695
|
|
670
|
-
|
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="
|
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="
|
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="✓" />'.html_safe
|
826
|
+
'<input name="utf8" type="hidden" value="✓" 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 =
|
841
|
-
|
857
|
+
method_tag = \
|
858
|
+
case method
|
859
|
+
when "get"
|
842
860
|
html_options["method"] = "get"
|
843
|
-
|
844
|
-
when
|
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
|
-
|
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") {
|
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(
|
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
|
-
|
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!] =
|
17
|
-
JS_ESCAPE_MAP["\342\200\251".force_encoding(Encoding::UTF_8).encode!] =
|
20
|
+
JS_ESCAPE_MAP[(+"\342\200\250").force_encoding(Encoding::UTF_8).encode!] = "
"
|
21
|
+
JS_ESCAPE_MAP[(+"\342\200\251").force_encoding(Encoding::UTF_8).encode!] = "
"
|
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
|
-
|
27
|
-
|
28
|
-
|
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')",
|
50
|
-
#
|
51
|
-
# Returns:
|
52
|
-
# <script
|
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
|
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
|
-
|
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:
|