actionview 4.2.11.1 → 5.2.4
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 +88 -286
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -6
- data/lib/action_view/base.rb +38 -28
- data/lib/action_view/buffers.rb +3 -1
- data/lib/action_view/context.rb +3 -3
- data/lib/action_view/dependency_tracker.rb +54 -20
- data/lib/action_view/digestor.rb +94 -83
- data/lib/action_view/flows.rb +11 -11
- data/lib/action_view/gem_version.rb +5 -3
- data/lib/action_view/helpers/active_model_helper.rb +17 -11
- data/lib/action_view/helpers/asset_tag_helper.rb +244 -62
- data/lib/action_view/helpers/asset_url_helper.rb +170 -67
- data/lib/action_view/helpers/atom_feed_helper.rb +19 -17
- data/lib/action_view/helpers/cache_helper.rb +105 -42
- data/lib/action_view/helpers/capture_helper.rb +16 -13
- data/lib/action_view/helpers/controller_helper.rb +15 -4
- data/lib/action_view/helpers/csp_helper.rb +24 -0
- data/lib/action_view/helpers/csrf_helper.rb +7 -5
- data/lib/action_view/helpers/date_helper.rb +170 -112
- data/lib/action_view/helpers/debug_helper.rb +7 -6
- data/lib/action_view/helpers/form_helper.rb +521 -127
- data/lib/action_view/helpers/form_options_helper.rb +109 -63
- data/lib/action_view/helpers/form_tag_helper.rb +110 -67
- data/lib/action_view/helpers/javascript_helper.rb +24 -11
- data/lib/action_view/helpers/number_helper.rb +77 -58
- data/lib/action_view/helpers/output_safety_helper.rb +36 -4
- data/lib/action_view/helpers/record_tag_helper.rb +14 -99
- data/lib/action_view/helpers/rendering_helper.rb +6 -5
- data/lib/action_view/helpers/sanitize_helper.rb +20 -15
- data/lib/action_view/helpers/tag_helper.rb +198 -73
- data/lib/action_view/helpers/tags/base.rb +134 -97
- data/lib/action_view/helpers/tags/check_box.rb +20 -18
- data/lib/action_view/helpers/tags/checkable.rb +4 -2
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +12 -33
- data/lib/action_view/helpers/tags/collection_helpers.rb +70 -36
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +6 -11
- data/lib/action_view/helpers/tags/collection_select.rb +4 -2
- data/lib/action_view/helpers/tags/color_field.rb +3 -1
- data/lib/action_view/helpers/tags/date_field.rb +2 -0
- data/lib/action_view/helpers/tags/date_select.rb +38 -36
- data/lib/action_view/helpers/tags/datetime_field.rb +4 -2
- data/lib/action_view/helpers/tags/datetime_local_field.rb +2 -0
- 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 +2 -0
- data/lib/action_view/helpers/tags/label.rb +3 -1
- data/lib/action_view/helpers/tags/month_field.rb +2 -0
- 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 -5
- 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 -9
- 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 -7
- data/lib/action_view/helpers/tags/time_field.rb +2 -0
- 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 +17 -13
- data/lib/action_view/helpers/tags/url_field.rb +2 -0
- data/lib/action_view/helpers/tags/week_field.rb +2 -0
- data/lib/action_view/helpers/tags.rb +3 -1
- data/lib/action_view/helpers/text_helper.rb +55 -36
- data/lib/action_view/helpers/translation_helper.rb +62 -31
- data/lib/action_view/helpers/url_helper.rb +159 -104
- data/lib/action_view/helpers.rb +5 -1
- data/lib/action_view/layouts.rb +65 -58
- data/lib/action_view/log_subscriber.rb +60 -8
- data/lib/action_view/lookup_context.rb +80 -65
- data/lib/action_view/model_naming.rb +3 -1
- data/lib/action_view/path_set.rb +30 -19
- data/lib/action_view/railtie.rb +39 -6
- data/lib/action_view/record_identifier.rb +53 -25
- data/lib/action_view/renderer/abstract_renderer.rb +21 -15
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +57 -0
- data/lib/action_view/renderer/partial_renderer.rb +218 -214
- data/lib/action_view/renderer/renderer.rb +8 -6
- data/lib/action_view/renderer/streaming_template_renderer.rb +50 -48
- data/lib/action_view/renderer/template_renderer.rb +67 -66
- data/lib/action_view/rendering.rb +19 -14
- data/lib/action_view/routing_url_for.rb +27 -17
- data/lib/action_view/tasks/cache_digests.rake +25 -0
- data/lib/action_view/template/error.rb +16 -16
- data/lib/action_view/template/handlers/builder.rb +10 -11
- data/lib/action_view/template/handlers/erb/erubi.rb +83 -0
- data/lib/action_view/template/handlers/erb.rb +9 -80
- data/lib/action_view/template/handlers/html.rb +11 -0
- data/lib/action_view/template/handlers/raw.rb +3 -3
- data/lib/action_view/template/handlers.rb +11 -7
- data/lib/action_view/template/html.rb +5 -5
- data/lib/action_view/template/resolver.rb +140 -115
- data/lib/action_view/template/text.rb +8 -9
- data/lib/action_view/template/types.rb +18 -18
- data/lib/action_view/template.rb +56 -31
- data/lib/action_view/test_case.rb +50 -29
- data/lib/action_view/testing/resolvers.rb +31 -31
- data/lib/action_view/version.rb +3 -1
- data/lib/action_view/view_paths.rb +28 -34
- data/lib/action_view.rb +8 -7
- data/lib/assets/compiled/rails-ujs.js +720 -0
- metadata +25 -24
- data/lib/action_view/tasks/dependencies.rake +0 -23
@@ -1,11 +1,13 @@
|
|
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"
|
5
7
|
|
6
8
|
module ActionView
|
7
9
|
# = Action View Form Tag Helpers
|
8
|
-
module Helpers
|
10
|
+
module Helpers #:nodoc:
|
9
11
|
# Provides a number of methods for creating form tags that don't rely on an Active Record object assigned to the template like
|
10
12
|
# FormHelper does. Instead, you provide the names and values manually.
|
11
13
|
#
|
@@ -18,9 +20,9 @@ module ActionView
|
|
18
20
|
include TextHelper
|
19
21
|
|
20
22
|
mattr_accessor :embed_authenticity_token_in_remote_forms
|
21
|
-
self.embed_authenticity_token_in_remote_forms =
|
23
|
+
self.embed_authenticity_token_in_remote_forms = nil
|
22
24
|
|
23
|
-
# Starts a form tag that points the action to
|
25
|
+
# Starts a form tag that points the action to a url configured with <tt>url_for_options</tt> just like
|
24
26
|
# ActionController::Base#url_for. The method for the form defaults to POST.
|
25
27
|
#
|
26
28
|
# ==== Options
|
@@ -80,7 +82,7 @@ module ActionView
|
|
80
82
|
# associated records. <tt>option_tags</tt> is a string containing the option tags for the select box.
|
81
83
|
#
|
82
84
|
# ==== Options
|
83
|
-
# * <tt>:multiple</tt> - If set to true the selection will allow multiple choices.
|
85
|
+
# * <tt>:multiple</tt> - If set to true, the selection will allow multiple choices.
|
84
86
|
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
|
85
87
|
# * <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
88
|
# * <tt>:prompt</tt> - Create a prompt option with blank value and the text asking user to select something.
|
@@ -93,27 +95,27 @@ module ActionView
|
|
93
95
|
# select_tag "people", options_from_collection_for_select(@people, "id", "name", "1")
|
94
96
|
# # <select id="people" name="people"><option value="1" selected="selected">David</option></select>
|
95
97
|
#
|
96
|
-
# select_tag "people", "<option>David</option>"
|
98
|
+
# select_tag "people", raw("<option>David</option>")
|
97
99
|
# # => <select id="people" name="people"><option>David</option></select>
|
98
100
|
#
|
99
|
-
# select_tag "count", "<option>1</option><option>2</option><option>3</option><option>4</option>"
|
101
|
+
# select_tag "count", raw("<option>1</option><option>2</option><option>3</option><option>4</option>")
|
100
102
|
# # => <select id="count" name="count"><option>1</option><option>2</option>
|
101
103
|
# # <option>3</option><option>4</option></select>
|
102
104
|
#
|
103
|
-
# select_tag "colors", "<option>Red</option><option>Green</option><option>Blue</option>"
|
105
|
+
# select_tag "colors", raw("<option>Red</option><option>Green</option><option>Blue</option>"), multiple: true
|
104
106
|
# # => <select id="colors" multiple="multiple" name="colors[]"><option>Red</option>
|
105
107
|
# # <option>Green</option><option>Blue</option></select>
|
106
108
|
#
|
107
|
-
# select_tag "locations", "<option>Home</option><option selected='selected'>Work</option><option>Out</option>"
|
109
|
+
# select_tag "locations", raw("<option>Home</option><option selected='selected'>Work</option><option>Out</option>")
|
108
110
|
# # => <select id="locations" name="locations"><option>Home</option><option selected='selected'>Work</option>
|
109
111
|
# # <option>Out</option></select>
|
110
112
|
#
|
111
|
-
# select_tag "access", "<option>Read</option><option>Write</option>"
|
113
|
+
# select_tag "access", raw("<option>Read</option><option>Write</option>"), multiple: true, class: 'form_input', id: 'unique_id'
|
112
114
|
# # => <select class="form_input" id="unique_id" multiple="multiple" name="access[]"><option>Read</option>
|
113
115
|
# # <option>Write</option></select>
|
114
116
|
#
|
115
117
|
# 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>
|
118
|
+
# # => <select id="people" name="people"><option value="" label=" "></option><option value="1">David</option></select>
|
117
119
|
#
|
118
120
|
# select_tag "people", options_from_collection_for_select(@people, "id", "name"), include_blank: "All"
|
119
121
|
# # => <select id="people" name="people"><option value="">All</option><option value="1">David</option></select>
|
@@ -121,7 +123,7 @@ module ActionView
|
|
121
123
|
# select_tag "people", options_from_collection_for_select(@people, "id", "name"), prompt: "Select something"
|
122
124
|
# # => <select id="people" name="people"><option value="">Select something</option><option value="1">David</option></select>
|
123
125
|
#
|
124
|
-
# select_tag "destination", "<option>NYC</option><option>Paris</option><option>Rome</option>"
|
126
|
+
# select_tag "destination", raw("<option>NYC</option><option>Paris</option><option>Rome</option>"), disabled: true
|
125
127
|
# # => <select disabled="disabled" id="destination" name="destination"><option>NYC</option>
|
126
128
|
# # <option>Paris</option><option>Rome</option></select>
|
127
129
|
#
|
@@ -134,21 +136,23 @@ module ActionView
|
|
134
136
|
|
135
137
|
if options.include?(:include_blank)
|
136
138
|
include_blank = options.delete(:include_blank)
|
139
|
+
options_for_blank_options_tag = { value: "" }
|
137
140
|
|
138
141
|
if include_blank == true
|
139
|
-
include_blank =
|
142
|
+
include_blank = ""
|
143
|
+
options_for_blank_options_tag[:label] = " "
|
140
144
|
end
|
141
145
|
|
142
146
|
if include_blank
|
143
|
-
option_tags = content_tag(
|
147
|
+
option_tags = content_tag("option".freeze, include_blank, options_for_blank_options_tag).safe_concat(option_tags)
|
144
148
|
end
|
145
149
|
end
|
146
150
|
|
147
151
|
if prompt = options.delete(:prompt)
|
148
|
-
option_tags = content_tag(
|
152
|
+
option_tags = content_tag("option".freeze, prompt, value: "").safe_concat(option_tags)
|
149
153
|
end
|
150
154
|
|
151
|
-
content_tag
|
155
|
+
content_tag "select".freeze, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
|
152
156
|
end
|
153
157
|
|
154
158
|
# Creates a standard text field; use these text fields to input smaller chunks of text like a username
|
@@ -159,6 +163,8 @@ module ActionView
|
|
159
163
|
# * <tt>:size</tt> - The number of visible characters that will fit in the input.
|
160
164
|
# * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
|
161
165
|
# * <tt>:placeholder</tt> - The text contained in the field by default which is removed when the field receives focus.
|
166
|
+
# If set to true, use a translation is found in the current I18n locale
|
167
|
+
# (through helpers.placeholders.<modelname>.<attribute>).
|
162
168
|
# * Any other key creates standard HTML attributes for the tag.
|
163
169
|
#
|
164
170
|
# ==== Examples
|
@@ -270,7 +276,7 @@ module ActionView
|
|
270
276
|
# file_field_tag 'file', accept: 'text/html', class: 'upload', value: 'index.html'
|
271
277
|
# # => <input accept="text/html" class="upload" id="file" name="file" type="file" value="index.html" />
|
272
278
|
def file_field_tag(name, options = {})
|
273
|
-
text_field_tag(name, nil, options.merge(type: :file))
|
279
|
+
text_field_tag(name, nil, convert_direct_upload_option_to_url(options.merge(type: :file)))
|
274
280
|
end
|
275
281
|
|
276
282
|
# Creates a password field, a masked text field that will hide the users input behind a mask character.
|
@@ -390,7 +396,7 @@ module ActionView
|
|
390
396
|
# # => <input checked="checked" id="receive_updates_no" name="receive_updates" type="radio" value="no" />
|
391
397
|
#
|
392
398
|
# radio_button_tag 'time_slot', "3:00 p.m.", false, disabled: true
|
393
|
-
# # => <input disabled="disabled" id="
|
399
|
+
# # => <input disabled="disabled" id="time_slot_3:00_p.m." name="time_slot" type="radio" value="3:00 p.m." />
|
394
400
|
#
|
395
401
|
# radio_button_tag 'color', "green", true, class: "color_input"
|
396
402
|
# # => <input checked="checked" class="color_input" id="color_green" name="color" type="radio" value="green" />
|
@@ -414,42 +420,45 @@ module ActionView
|
|
414
420
|
# the form is processed normally, otherwise no action is taken.
|
415
421
|
# * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a
|
416
422
|
# disabled version of the submit button when the form is submitted. This feature is
|
417
|
-
# provided by the unobtrusive JavaScript driver.
|
423
|
+
# provided by the unobtrusive JavaScript driver. To disable this feature for a single submit tag
|
424
|
+
# pass <tt>:data => { disable_with: false }</tt> Defaults to value attribute.
|
418
425
|
#
|
419
426
|
# ==== Examples
|
420
427
|
# submit_tag
|
421
|
-
# # => <input name="commit" type="submit" value="Save changes" />
|
428
|
+
# # => <input name="commit" data-disable-with="Save changes" type="submit" value="Save changes" />
|
422
429
|
#
|
423
430
|
# submit_tag "Edit this article"
|
424
|
-
# # => <input name="commit" type="submit" value="Edit this article" />
|
431
|
+
# # => <input name="commit" data-disable-with="Edit this article" type="submit" value="Edit this article" />
|
425
432
|
#
|
426
433
|
# submit_tag "Save edits", disabled: true
|
427
|
-
# # => <input disabled="disabled" name="commit" type="submit" value="Save edits" />
|
434
|
+
# # => <input disabled="disabled" name="commit" data-disable-with="Save edits" type="submit" value="Save edits" />
|
428
435
|
#
|
429
|
-
# submit_tag "Complete sale", data: { disable_with: "
|
430
|
-
# # => <input name="commit" data-disable-with="
|
436
|
+
# submit_tag "Complete sale", data: { disable_with: "Submitting..." }
|
437
|
+
# # => <input name="commit" data-disable-with="Submitting..." type="submit" value="Complete sale" />
|
431
438
|
#
|
432
439
|
# submit_tag nil, class: "form_submit"
|
433
440
|
# # => <input class="form_submit" name="commit" type="submit" />
|
434
441
|
#
|
435
442
|
# submit_tag "Edit", class: "edit_button"
|
436
|
-
# # => <input class="edit_button" name="commit" type="submit" value="Edit" />
|
443
|
+
# # => <input class="edit_button" data-disable-with="Edit" name="commit" type="submit" value="Edit" />
|
437
444
|
#
|
438
445
|
# submit_tag "Save", data: { confirm: "Are you sure?" }
|
439
|
-
# # => <input name='commit' type='submit' value='Save' data-confirm="Are you sure?" />
|
446
|
+
# # => <input name='commit' type='submit' value='Save' data-disable-with="Save" data-confirm="Are you sure?" />
|
440
447
|
#
|
441
448
|
def submit_tag(value = "Save changes", options = {})
|
442
|
-
options = options.
|
443
|
-
|
444
|
-
|
449
|
+
options = options.deep_stringify_keys
|
450
|
+
tag_options = { "type" => "submit", "name" => "commit", "value" => value }.update(options)
|
451
|
+
set_default_disable_with value, tag_options
|
452
|
+
tag :input, tag_options
|
445
453
|
end
|
446
454
|
|
447
455
|
# 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
|
456
|
+
# <tt>reset</tt> button or a generic button which can be used in
|
449
457
|
# JavaScript, for example. You can use the button tag as a regular
|
450
458
|
# submit tag but it isn't supported in legacy browsers. However,
|
451
|
-
# the button tag
|
452
|
-
# so this helper will also accept a block.
|
459
|
+
# the button tag does allow for richer labels such as images and emphasis,
|
460
|
+
# so this helper will also accept a block. By default, it will create
|
461
|
+
# a button tag with type <tt>submit</tt>, if type is not given.
|
453
462
|
#
|
454
463
|
# ==== Options
|
455
464
|
# * <tt>:data</tt> - This option can be used to add custom data attributes.
|
@@ -472,6 +481,15 @@ module ActionView
|
|
472
481
|
# button_tag
|
473
482
|
# # => <button name="button" type="submit">Button</button>
|
474
483
|
#
|
484
|
+
# button_tag 'Reset', type: 'reset'
|
485
|
+
# # => <button name="button" type="reset">Reset</button>
|
486
|
+
#
|
487
|
+
# button_tag 'Button', type: 'button'
|
488
|
+
# # => <button name="button" type="button">Button</button>
|
489
|
+
#
|
490
|
+
# button_tag 'Reset', type: 'reset', disabled: true
|
491
|
+
# # => <button name="button" type="reset" disabled="disabled">Reset</button>
|
492
|
+
#
|
475
493
|
# button_tag(type: 'button') do
|
476
494
|
# content_tag(:strong, 'Ask me!')
|
477
495
|
# end
|
@@ -479,6 +497,9 @@ module ActionView
|
|
479
497
|
# # <strong>Ask me!</strong>
|
480
498
|
# # </button>
|
481
499
|
#
|
500
|
+
# button_tag "Save", data: { confirm: "Are you sure?" }
|
501
|
+
# # => <button name="button" type="submit" data-confirm="Are you sure?">Save</button>
|
502
|
+
#
|
482
503
|
# button_tag "Checkout", data: { disable_with: "Please wait..." }
|
483
504
|
# # => <button data-disable-with="Please wait..." name="button" type="submit">Checkout</button>
|
484
505
|
#
|
@@ -489,12 +510,12 @@ module ActionView
|
|
489
510
|
options ||= {}
|
490
511
|
end
|
491
512
|
|
492
|
-
options = {
|
513
|
+
options = { "name" => "button", "type" => "submit" }.merge!(options.stringify_keys)
|
493
514
|
|
494
515
|
if block_given?
|
495
516
|
content_tag :button, options, &block
|
496
517
|
else
|
497
|
-
content_tag :button, content_or_options ||
|
518
|
+
content_tag :button, content_or_options || "Button", options
|
498
519
|
end
|
499
520
|
end
|
500
521
|
|
@@ -515,22 +536,23 @@ module ActionView
|
|
515
536
|
#
|
516
537
|
# ==== Examples
|
517
538
|
# image_submit_tag("login.png")
|
518
|
-
# # => <input
|
539
|
+
# # => <input src="/assets/login.png" type="image" />
|
519
540
|
#
|
520
541
|
# image_submit_tag("purchase.png", disabled: true)
|
521
|
-
# # => <input
|
542
|
+
# # => <input disabled="disabled" src="/assets/purchase.png" type="image" />
|
522
543
|
#
|
523
544
|
# image_submit_tag("search.png", class: 'search_button', alt: 'Find')
|
524
|
-
# # => <input
|
545
|
+
# # => <input class="search_button" src="/assets/search.png" type="image" />
|
525
546
|
#
|
526
547
|
# image_submit_tag("agree.png", disabled: true, class: "agree_disagree_button")
|
527
|
-
# # => <input
|
548
|
+
# # => <input class="agree_disagree_button" disabled="disabled" src="/assets/agree.png" type="image" />
|
528
549
|
#
|
529
550
|
# image_submit_tag("save.png", data: { confirm: "Are you sure?" })
|
530
|
-
# # => <input
|
551
|
+
# # => <input src="/assets/save.png" data-confirm="Are you sure?" type="image" />
|
531
552
|
def image_submit_tag(source, options = {})
|
532
553
|
options = options.stringify_keys
|
533
|
-
|
554
|
+
src = path_to_image(source, skip_pipeline: options.delete("skip_pipeline"))
|
555
|
+
tag :input, { "type" => "image", "src" => src }.update(options)
|
534
556
|
end
|
535
557
|
|
536
558
|
# Creates a field set for grouping HTML form elements.
|
@@ -555,7 +577,7 @@ module ActionView
|
|
555
577
|
# # => <fieldset class="format"><p><input id="name" name="name" type="text" /></p></fieldset>
|
556
578
|
def field_set_tag(legend = nil, options = nil, &block)
|
557
579
|
output = tag(:fieldset, options, true)
|
558
|
-
output.safe_concat(content_tag(
|
580
|
+
output.safe_concat(content_tag("legend".freeze, legend)) unless legend.blank?
|
559
581
|
output.concat(capture(&block)) if block_given?
|
560
582
|
output.safe_concat("</fieldset>")
|
561
583
|
end
|
@@ -656,7 +678,7 @@ module ActionView
|
|
656
678
|
text_field_tag(name, value, options.merge(type: :time))
|
657
679
|
end
|
658
680
|
|
659
|
-
# Creates a text field of type "datetime".
|
681
|
+
# Creates a text field of type "datetime-local".
|
660
682
|
#
|
661
683
|
# === Options
|
662
684
|
# * <tt>:min</tt> - The minimum acceptable value.
|
@@ -664,19 +686,10 @@ module ActionView
|
|
664
686
|
# * <tt>:step</tt> - The acceptable value granularity.
|
665
687
|
# * Otherwise accepts the same options as text_field_tag.
|
666
688
|
def datetime_field_tag(name, value = nil, options = {})
|
667
|
-
text_field_tag(name, value, options.merge(type:
|
689
|
+
text_field_tag(name, value, options.merge(type: "datetime-local"))
|
668
690
|
end
|
669
691
|
|
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
|
692
|
+
alias datetime_local_field_tag datetime_field_tag
|
680
693
|
|
681
694
|
# Creates a text field of type "month".
|
682
695
|
#
|
@@ -776,10 +789,10 @@ module ActionView
|
|
776
789
|
# # => <input id="quantity" name="quantity" min="1" max="9" type="number" />
|
777
790
|
#
|
778
791
|
# number_field_tag 'quantity', nil, min: 1, max: 10
|
779
|
-
# # => <input id="quantity" name="quantity" min="1" max="
|
792
|
+
# # => <input id="quantity" name="quantity" min="1" max="10" type="number" />
|
780
793
|
#
|
781
794
|
# number_field_tag 'quantity', nil, min: 1, max: 10, step: 2
|
782
|
-
# # => <input id="quantity" name="quantity" min="1" max="
|
795
|
+
# # => <input id="quantity" name="quantity" min="1" max="10" step="2" type="number" />
|
783
796
|
#
|
784
797
|
# number_field_tag 'quantity', '1', class: 'special_input', disabled: true
|
785
798
|
# # => <input disabled="disabled" class="special_input" id="quantity" name="quantity" type="number" value="1" />
|
@@ -835,19 +848,26 @@ module ActionView
|
|
835
848
|
|
836
849
|
def extra_tags_for_form(html_options)
|
837
850
|
authenticity_token = html_options.delete("authenticity_token")
|
838
|
-
method = html_options.delete("method").to_s
|
851
|
+
method = html_options.delete("method").to_s.downcase
|
839
852
|
|
840
|
-
method_tag =
|
841
|
-
|
853
|
+
method_tag = \
|
854
|
+
case method
|
855
|
+
when "get"
|
842
856
|
html_options["method"] = "get"
|
843
|
-
|
844
|
-
when
|
857
|
+
""
|
858
|
+
when "post", ""
|
845
859
|
html_options["method"] = "post"
|
846
|
-
token_tag(authenticity_token
|
860
|
+
token_tag(authenticity_token, form_options: {
|
861
|
+
action: html_options["action"],
|
862
|
+
method: "post"
|
863
|
+
})
|
847
864
|
else
|
848
865
|
html_options["method"] = "post"
|
849
|
-
method_tag(method) + token_tag(authenticity_token
|
850
|
-
|
866
|
+
method_tag(method) + token_tag(authenticity_token, form_options: {
|
867
|
+
action: html_options["action"],
|
868
|
+
method: method
|
869
|
+
})
|
870
|
+
end
|
851
871
|
|
852
872
|
if html_options.delete("enforce_utf8") { true }
|
853
873
|
utf8_enforcer_tag + method_tag
|
@@ -869,7 +889,30 @@ module ActionView
|
|
869
889
|
|
870
890
|
# see http://www.w3.org/TR/html4/types.html#type-name
|
871
891
|
def sanitize_to_id(name)
|
872
|
-
name.to_s.delete(
|
892
|
+
name.to_s.delete("]").tr("^-a-zA-Z0-9:.", "_")
|
893
|
+
end
|
894
|
+
|
895
|
+
def set_default_disable_with(value, tag_options)
|
896
|
+
return unless ActionView::Base.automatically_disable_submit_tag
|
897
|
+
data = tag_options["data"]
|
898
|
+
|
899
|
+
unless tag_options["data-disable-with"] == false || (data && data["disable_with"] == false)
|
900
|
+
disable_with_text = tag_options["data-disable-with"]
|
901
|
+
disable_with_text ||= data["disable_with"] if data
|
902
|
+
disable_with_text ||= value.to_s.clone
|
903
|
+
tag_options.deep_merge!("data" => { "disable_with" => disable_with_text })
|
904
|
+
else
|
905
|
+
data.delete("disable_with") if data
|
906
|
+
end
|
907
|
+
|
908
|
+
tag_options.delete("data-disable-with")
|
909
|
+
end
|
910
|
+
|
911
|
+
def convert_direct_upload_option_to_url(options)
|
912
|
+
if options.delete(:direct_upload) && respond_to?(:rails_direct_uploads_url)
|
913
|
+
options["data-direct-upload-url"] = rails_direct_uploads_url
|
914
|
+
end
|
915
|
+
options
|
873
916
|
end
|
874
917
|
end
|
875
918
|
end
|
@@ -1,11 +1,13 @@
|
|
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',
|
@@ -13,21 +15,21 @@ module ActionView
|
|
13
15
|
"'" => "\\'"
|
14
16
|
}
|
15
17
|
|
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!] =
|
18
|
+
JS_ESCAPE_MAP["\342\200\250".dup.force_encoding(Encoding::UTF_8).encode!] = "
"
|
19
|
+
JS_ESCAPE_MAP["\342\200\251".dup.force_encoding(Encoding::UTF_8).encode!] = "
"
|
18
20
|
|
19
21
|
# Escapes carriage returns and single and double quotes for JavaScript segments.
|
20
22
|
#
|
21
23
|
# Also available through the alias j(). This is particularly helpful in JavaScript
|
22
24
|
# responses, like:
|
23
25
|
#
|
24
|
-
# $('some_element').replaceWith('<%=j render 'some/element_template' %>');
|
26
|
+
# $('some_element').replaceWith('<%= j render 'some/element_template' %>');
|
25
27
|
def escape_javascript(javascript)
|
26
28
|
if javascript
|
27
|
-
result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|\342\200\251|[\n\r"'])/u) {|match| JS_ESCAPE_MAP[match] }
|
29
|
+
result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|\342\200\251|[\n\r"'])/u) { |match| JS_ESCAPE_MAP[match] }
|
28
30
|
javascript.html_safe? ? result.html_safe : result
|
29
31
|
else
|
30
|
-
|
32
|
+
""
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
@@ -47,8 +49,8 @@ module ActionView
|
|
47
49
|
# tag.
|
48
50
|
#
|
49
51
|
# javascript_tag "alert('All is good')", defer: 'defer'
|
50
|
-
#
|
51
|
-
# Returns:
|
52
|
+
#
|
53
|
+
# Returns:
|
52
54
|
# <script defer="defer">
|
53
55
|
# //<![CDATA[
|
54
56
|
# alert('All is good')
|
@@ -61,6 +63,13 @@ module ActionView
|
|
61
63
|
# <%= javascript_tag defer: 'defer' do -%>
|
62
64
|
# alert('All is good')
|
63
65
|
# <% end -%>
|
66
|
+
#
|
67
|
+
# If you have a content security policy enabled then you can add an automatic
|
68
|
+
# nonce value by passing +nonce: true+ as part of +html_options+. Example:
|
69
|
+
#
|
70
|
+
# <%= javascript_tag nonce: true do -%>
|
71
|
+
# alert('All is good')
|
72
|
+
# <% end -%>
|
64
73
|
def javascript_tag(content_or_options_with_block = nil, html_options = {}, &block)
|
65
74
|
content =
|
66
75
|
if block_given?
|
@@ -70,7 +79,11 @@ module ActionView
|
|
70
79
|
content_or_options_with_block
|
71
80
|
end
|
72
81
|
|
73
|
-
|
82
|
+
if html_options[:nonce] == true
|
83
|
+
html_options[:nonce] = content_security_policy_nonce
|
84
|
+
end
|
85
|
+
|
86
|
+
content_tag("script".freeze, javascript_cdata_section(content), html_options)
|
74
87
|
end
|
75
88
|
|
76
89
|
def javascript_cdata_section(content) #:nodoc:
|