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