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,13 +1,12 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "active_support/core_ext/hash/keys"
|
4
|
+
require "active_support/core_ext/string/output_safety"
|
5
|
+
require "active_support/number_helper"
|
6
6
|
|
7
7
|
module ActionView
|
8
8
|
# = Action View Number Helpers
|
9
9
|
module Helpers #:nodoc:
|
10
|
-
|
11
10
|
# Provides methods for converting numbers into formatted strings.
|
12
11
|
# Methods are provided for phone numbers, currency, percentage,
|
13
12
|
# precision, positional notation, file size and pretty printing.
|
@@ -15,7 +14,6 @@ module ActionView
|
|
15
14
|
# Most methods expect a +number+ argument, and will return it
|
16
15
|
# unchanged if can't be converted into a valid number.
|
17
16
|
module NumberHelper
|
18
|
-
|
19
17
|
# Raised when argument +number+ param given to the helpers is invalid and
|
20
18
|
# the option :raise is set to +true+.
|
21
19
|
class InvalidNumberError < StandardError
|
@@ -25,7 +23,7 @@ module ActionView
|
|
25
23
|
end
|
26
24
|
end
|
27
25
|
|
28
|
-
# Formats a +number+ into a
|
26
|
+
# Formats a +number+ into a phone number (US by default e.g., (555)
|
29
27
|
# 123-9876). You can customize the format in the +options+ hash.
|
30
28
|
#
|
31
29
|
# ==== Options
|
@@ -37,6 +35,8 @@ module ActionView
|
|
37
35
|
# end of the generated number.
|
38
36
|
# * <tt>:country_code</tt> - Sets the country code for the phone
|
39
37
|
# number.
|
38
|
+
# * <tt>:pattern</tt> - Specifies how the number is divided into three
|
39
|
+
# groups with the custom regexp to override the default format.
|
40
40
|
# * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
|
41
41
|
# the argument is invalid.
|
42
42
|
#
|
@@ -54,6 +54,11 @@ module ActionView
|
|
54
54
|
#
|
55
55
|
# number_to_phone(1235551234, country_code: 1, extension: 1343, delimiter: ".")
|
56
56
|
# # => +1.123.555.1234 x 1343
|
57
|
+
#
|
58
|
+
# number_to_phone(75561234567, pattern: /(\d{1,4})(\d{4})(\d{4})$/, area_code: true)
|
59
|
+
# # => "(755) 6123-4567"
|
60
|
+
# number_to_phone(13312345678, pattern: /(\d{3})(\d{4})(\d{4})$/)
|
61
|
+
# # => "133-1234-5678"
|
57
62
|
def number_to_phone(number, options = {})
|
58
63
|
return unless number
|
59
64
|
options = options.symbolize_keys
|
@@ -65,6 +70,14 @@ module ActionView
|
|
65
70
|
# Formats a +number+ into a currency string (e.g., $13.65). You
|
66
71
|
# can customize the format in the +options+ hash.
|
67
72
|
#
|
73
|
+
# The currency unit and number formatting of the current locale will be used
|
74
|
+
# unless otherwise specified in the provided options. No currency conversion
|
75
|
+
# is performed. If the user is given a way to change their locale, they will
|
76
|
+
# also be able to change the relative value of the currency displayed with
|
77
|
+
# this helper. If your application will ever support multiple locales, you
|
78
|
+
# may want to specify a constant <tt>:locale</tt> option or consider
|
79
|
+
# using a library capable of currency conversion.
|
80
|
+
#
|
68
81
|
# ==== Options
|
69
82
|
#
|
70
83
|
# * <tt>:locale</tt> - Sets the locale to be used for formatting
|
@@ -81,12 +94,15 @@ module ActionView
|
|
81
94
|
# (defaults to "%u%n"). Fields are <tt>%u</tt> for the
|
82
95
|
# currency, and <tt>%n</tt> for the number.
|
83
96
|
# * <tt>:negative_format</tt> - Sets the format for negative
|
84
|
-
# numbers (defaults to prepending
|
97
|
+
# numbers (defaults to prepending a hyphen to the formatted
|
85
98
|
# number given by <tt>:format</tt>). Accepts the same fields
|
86
99
|
# than <tt>:format</tt>, except <tt>%n</tt> is here the
|
87
100
|
# absolute value of the number.
|
88
101
|
# * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
|
89
102
|
# the argument is invalid.
|
103
|
+
# * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
|
104
|
+
# insignificant zeros after the decimal separator (defaults to
|
105
|
+
# +false+).
|
90
106
|
#
|
91
107
|
# ==== Examples
|
92
108
|
#
|
@@ -98,12 +114,16 @@ module ActionView
|
|
98
114
|
#
|
99
115
|
# number_to_currency("123a456", raise: true) # => InvalidNumberError
|
100
116
|
#
|
117
|
+
# number_to_currency(-0.456789, precision: 0)
|
118
|
+
# # => "$0"
|
101
119
|
# number_to_currency(-1234567890.50, negative_format: "(%u%n)")
|
102
120
|
# # => ($1,234,567,890.50)
|
103
121
|
# number_to_currency(1234567890.50, unit: "R$", separator: ",", delimiter: "")
|
104
122
|
# # => R$1234567890,50
|
105
123
|
# number_to_currency(1234567890.50, unit: "R$", separator: ",", delimiter: "", format: "%n %u")
|
106
124
|
# # => 1234567890,50 R$
|
125
|
+
# number_to_currency(1234567890.50, strip_insignificant_zeros: true)
|
126
|
+
# # => "$1,234,567,890.5"
|
107
127
|
def number_to_currency(number, options = {})
|
108
128
|
delegate_number_helper_method(:number_to_currency, number, options)
|
109
129
|
end
|
@@ -117,8 +137,8 @@ module ActionView
|
|
117
137
|
# (defaults to current locale).
|
118
138
|
# * <tt>:precision</tt> - Sets the precision of the number
|
119
139
|
# (defaults to 3).
|
120
|
-
# * <tt>:significant</tt> - If +true+, precision will be the
|
121
|
-
# of significant_digits. If +false+, the
|
140
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
141
|
+
# of significant_digits. If +false+, the number of fractional
|
122
142
|
# digits (defaults to +false+).
|
123
143
|
# * <tt>:separator</tt> - Sets the separator between the
|
124
144
|
# fractional and integer digits (defaults to ".").
|
@@ -141,7 +161,7 @@ module ActionView
|
|
141
161
|
# number_to_percentage(302.24398923423, precision: 5) # => 302.24399%
|
142
162
|
# number_to_percentage(1000, locale: :fr) # => 1 000,000%
|
143
163
|
# number_to_percentage("98a") # => 98a%
|
144
|
-
# number_to_percentage(100, format: "%n %") # => 100 %
|
164
|
+
# number_to_percentage(100, format: "%n %") # => 100.000 %
|
145
165
|
#
|
146
166
|
# number_to_percentage("98a", raise: true) # => InvalidNumberError
|
147
167
|
def number_to_percentage(number, options = {})
|
@@ -160,6 +180,9 @@ module ActionView
|
|
160
180
|
# to ",").
|
161
181
|
# * <tt>:separator</tt> - Sets the separator between the
|
162
182
|
# fractional and integer digits (defaults to ".").
|
183
|
+
# * <tt>:delimiter_pattern</tt> - Sets a custom regular expression used for
|
184
|
+
# deriving the placement of delimiter. Helpful when using currency formats
|
185
|
+
# like INR.
|
163
186
|
# * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
|
164
187
|
# the argument is invalid.
|
165
188
|
#
|
@@ -176,6 +199,9 @@ module ActionView
|
|
176
199
|
# number_with_delimiter(98765432.98, delimiter: " ", separator: ",")
|
177
200
|
# # => 98 765 432,98
|
178
201
|
#
|
202
|
+
# number_with_delimiter("123456.78",
|
203
|
+
# delimiter_pattern: /(\d+?)(?=(\d\d)+(\d)(?!\d))/) # => "1,23,456.78"
|
204
|
+
#
|
179
205
|
# number_with_delimiter("112a", raise: true) # => raise InvalidNumberError
|
180
206
|
def number_with_delimiter(number, options = {})
|
181
207
|
delegate_number_helper_method(:number_to_delimited, number, options)
|
@@ -192,8 +218,8 @@ module ActionView
|
|
192
218
|
# (defaults to current locale).
|
193
219
|
# * <tt>:precision</tt> - Sets the precision of the number
|
194
220
|
# (defaults to 3).
|
195
|
-
# * <tt>:significant</tt> - If +true+, precision will be the
|
196
|
-
# of significant_digits. If +false+, the
|
221
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
222
|
+
# of significant_digits. If +false+, the number of fractional
|
197
223
|
# digits (defaults to +false+).
|
198
224
|
# * <tt>:separator</tt> - Sets the separator between the
|
199
225
|
# fractional and integer digits (defaults to ".").
|
@@ -240,8 +266,8 @@ module ActionView
|
|
240
266
|
# (defaults to current locale).
|
241
267
|
# * <tt>:precision</tt> - Sets the precision of the number
|
242
268
|
# (defaults to 3).
|
243
|
-
# * <tt>:significant</tt> - If +true+, precision will be the
|
244
|
-
# of significant_digits. If +false+, the
|
269
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
270
|
+
# of significant_digits. If +false+, the number of fractional
|
245
271
|
# digits (defaults to +true+)
|
246
272
|
# * <tt>:separator</tt> - Sets the separator between the
|
247
273
|
# fractional and integer digits (defaults to ".").
|
@@ -250,8 +276,6 @@ module ActionView
|
|
250
276
|
# * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
|
251
277
|
# insignificant zeros after the decimal separator (defaults to
|
252
278
|
# +true+)
|
253
|
-
# * <tt>:prefix</tt> - If +:si+ formats the number using the SI
|
254
|
-
# prefix (defaults to :binary)
|
255
279
|
# * <tt>:raise</tt> - If true, raises +InvalidNumberError+ when
|
256
280
|
# the argument is invalid.
|
257
281
|
#
|
@@ -263,6 +287,8 @@ module ActionView
|
|
263
287
|
# number_to_human_size(1234567) # => 1.18 MB
|
264
288
|
# number_to_human_size(1234567890) # => 1.15 GB
|
265
289
|
# number_to_human_size(1234567890123) # => 1.12 TB
|
290
|
+
# number_to_human_size(1234567890123456) # => 1.1 PB
|
291
|
+
# number_to_human_size(1234567890123456789) # => 1.07 EB
|
266
292
|
# number_to_human_size(1234567, precision: 2) # => 1.2 MB
|
267
293
|
# number_to_human_size(483989, precision: 2) # => 470 KB
|
268
294
|
# number_to_human_size(1234567, precision: 2, separator: ',') # => 1,2 MB
|
@@ -280,7 +306,7 @@ module ActionView
|
|
280
306
|
# See <tt>number_to_human_size</tt> if you want to print a file
|
281
307
|
# size.
|
282
308
|
#
|
283
|
-
# You can also define
|
309
|
+
# You can also define your own unit-quantifier names if you want
|
284
310
|
# to use other decimal units (eg.: 1500 becomes "1.5
|
285
311
|
# kilometers", 0.150 becomes "150 milliliters", etc). You may
|
286
312
|
# define a wide range of unit quantifiers, even fractional ones
|
@@ -292,8 +318,8 @@ module ActionView
|
|
292
318
|
# (defaults to current locale).
|
293
319
|
# * <tt>:precision</tt> - Sets the precision of the number
|
294
320
|
# (defaults to 3).
|
295
|
-
# * <tt>:significant</tt> - If +true+, precision will be the
|
296
|
-
# of significant_digits. If +false+, the
|
321
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
322
|
+
# of significant_digits. If +false+, the number of fractional
|
297
323
|
# digits (defaults to +true+)
|
298
324
|
# * <tt>:separator</tt> - Sets the separator between the
|
299
325
|
# fractional and integer digits (defaults to ".").
|
@@ -379,54 +405,53 @@ module ActionView
|
|
379
405
|
end
|
380
406
|
|
381
407
|
private
|
408
|
+
def delegate_number_helper_method(method, number, options)
|
409
|
+
return unless number
|
410
|
+
options = escape_unsafe_options(options.symbolize_keys)
|
382
411
|
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
wrap_with_output_safety_handling(number, options.delete(:raise)) {
|
388
|
-
ActiveSupport::NumberHelper.public_send(method, number, options)
|
389
|
-
}
|
390
|
-
end
|
412
|
+
wrap_with_output_safety_handling(number, options.delete(:raise)) {
|
413
|
+
ActiveSupport::NumberHelper.public_send(method, number, options)
|
414
|
+
}
|
415
|
+
end
|
391
416
|
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
417
|
+
def escape_unsafe_options(options)
|
418
|
+
options[:format] = ERB::Util.html_escape(options[:format]) if options[:format]
|
419
|
+
options[:negative_format] = ERB::Util.html_escape(options[:negative_format]) if options[:negative_format]
|
420
|
+
options[:separator] = ERB::Util.html_escape(options[:separator]) if options[:separator]
|
421
|
+
options[:delimiter] = ERB::Util.html_escape(options[:delimiter]) if options[:delimiter]
|
422
|
+
options[:unit] = ERB::Util.html_escape(options[:unit]) if options[:unit] && !options[:unit].html_safe?
|
423
|
+
options[:units] = escape_units(options[:units]) if options[:units] && Hash === options[:units]
|
424
|
+
options
|
425
|
+
end
|
401
426
|
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
427
|
+
def escape_units(units)
|
428
|
+
Hash[units.map do |k, v|
|
429
|
+
[k, ERB::Util.html_escape(v)]
|
430
|
+
end]
|
431
|
+
end
|
407
432
|
|
408
|
-
|
409
|
-
|
410
|
-
|
433
|
+
def wrap_with_output_safety_handling(number, raise_on_invalid, &block)
|
434
|
+
valid_float = valid_float?(number)
|
435
|
+
raise InvalidNumberError, number if raise_on_invalid && !valid_float
|
411
436
|
|
412
|
-
|
437
|
+
formatted_number = yield
|
413
438
|
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
439
|
+
if valid_float || number.html_safe?
|
440
|
+
formatted_number.html_safe
|
441
|
+
else
|
442
|
+
formatted_number
|
443
|
+
end
|
418
444
|
end
|
419
|
-
end
|
420
445
|
|
421
|
-
|
422
|
-
|
423
|
-
|
446
|
+
def valid_float?(number)
|
447
|
+
!parse_float(number, false).nil?
|
448
|
+
end
|
424
449
|
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
450
|
+
def parse_float(number, raise_error)
|
451
|
+
Float(number)
|
452
|
+
rescue ArgumentError, TypeError
|
453
|
+
raise InvalidNumberError, number if raise_error
|
454
|
+
end
|
430
455
|
end
|
431
456
|
end
|
432
457
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/output_safety"
|
2
4
|
|
3
5
|
module ActionView #:nodoc:
|
4
6
|
# = Action View Raw Output Helper
|
@@ -22,17 +24,47 @@ module ActionView #:nodoc:
|
|
22
24
|
# the supplied separator, are HTML escaped unless they are HTML
|
23
25
|
# safe, and the returned string is marked as HTML safe.
|
24
26
|
#
|
25
|
-
# safe_join(["<p>foo</p>"
|
27
|
+
# safe_join([raw("<p>foo</p>"), "<p>bar</p>"], "<br />")
|
26
28
|
# # => "<p>foo</p><br /><p>bar</p>"
|
27
29
|
#
|
28
|
-
# safe_join(["<p>foo</p>"
|
30
|
+
# safe_join([raw("<p>foo</p>"), raw("<p>bar</p>")], raw("<br />"))
|
29
31
|
# # => "<p>foo</p><br /><p>bar</p>"
|
30
32
|
#
|
31
|
-
def safe_join(array, sep
|
33
|
+
def safe_join(array, sep = $,)
|
32
34
|
sep = ERB::Util.unwrapped_html_escape(sep)
|
33
35
|
|
34
36
|
array.flatten.map! { |i| ERB::Util.unwrapped_html_escape(i) }.join(sep).html_safe
|
35
37
|
end
|
38
|
+
|
39
|
+
# Converts the array to a comma-separated sentence where the last element is
|
40
|
+
# joined by the connector word. This is the html_safe-aware version of
|
41
|
+
# ActiveSupport's {Array#to_sentence}[https://api.rubyonrails.org/classes/Array.html#method-i-to_sentence].
|
42
|
+
#
|
43
|
+
def to_sentence(array, options = {})
|
44
|
+
options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
|
45
|
+
|
46
|
+
default_connectors = {
|
47
|
+
words_connector: ", ",
|
48
|
+
two_words_connector: " and ",
|
49
|
+
last_word_connector: ", and "
|
50
|
+
}
|
51
|
+
if defined?(I18n)
|
52
|
+
i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
|
53
|
+
default_connectors.merge!(i18n_connectors)
|
54
|
+
end
|
55
|
+
options = default_connectors.merge!(options)
|
56
|
+
|
57
|
+
case array.length
|
58
|
+
when 0
|
59
|
+
"".html_safe
|
60
|
+
when 1
|
61
|
+
ERB::Util.html_escape(array[0])
|
62
|
+
when 2
|
63
|
+
safe_join([array[0], array[1]], options[:two_words_connector])
|
64
|
+
else
|
65
|
+
safe_join([safe_join(array[0...-1], options[:words_connector]), options[:last_word_connector], array[-1]], nil)
|
66
|
+
end
|
67
|
+
end
|
36
68
|
end
|
37
69
|
end
|
38
70
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionView
|
2
|
-
module Helpers
|
4
|
+
module Helpers #:nodoc:
|
3
5
|
# = Action View Rendering
|
4
6
|
#
|
5
7
|
# Implements methods that allow rendering from a view context.
|
@@ -11,14 +13,13 @@ module ActionView
|
|
11
13
|
# * <tt>:partial</tt> - See <tt>ActionView::PartialRenderer</tt>.
|
12
14
|
# * <tt>:file</tt> - Renders an explicit template file (this used to be the old default), add :locals to pass in those.
|
13
15
|
# * <tt>:inline</tt> - Renders an inline template similar to how it's done in the controller.
|
14
|
-
# * <tt>:text</tt> - Renders the text passed in out.
|
15
16
|
# * <tt>:plain</tt> - Renders the text passed in out. Setting the content
|
16
17
|
# type as <tt>text/plain</tt>.
|
17
18
|
# * <tt>:html</tt> - Renders the HTML safe string passed in out, otherwise
|
18
19
|
# performs HTML escape on the string first. Setting the content type as
|
19
20
|
# <tt>text/html</tt>.
|
20
21
|
# * <tt>:body</tt> - Renders the text passed in, and inherits the content
|
21
|
-
# type of <tt>text/
|
22
|
+
# type of <tt>text/plain</tt> from <tt>ActionDispatch::Response</tt>
|
22
23
|
# object.
|
23
24
|
#
|
24
25
|
# If no options hash is passed or :update specified, the default is to render a partial and use the second parameter
|
@@ -26,13 +27,15 @@ module ActionView
|
|
26
27
|
def render(options = {}, locals = {}, &block)
|
27
28
|
case options
|
28
29
|
when Hash
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
in_rendering_context(options) do |renderer|
|
31
|
+
if block_given?
|
32
|
+
view_renderer.render_partial(self, options.merge(partial: options[:layout]), &block)
|
33
|
+
else
|
34
|
+
view_renderer.render(self, options)
|
35
|
+
end
|
33
36
|
end
|
34
37
|
else
|
35
|
-
view_renderer.render_partial(self, :
|
38
|
+
view_renderer.render_partial(self, partial: options, locals: locals, &block)
|
36
39
|
end
|
37
40
|
end
|
38
41
|
|
@@ -1,28 +1,28 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails-html-sanitizer"
|
4
4
|
|
5
5
|
module ActionView
|
6
6
|
# = Action View Sanitize Helpers
|
7
|
-
module Helpers
|
7
|
+
module Helpers #:nodoc:
|
8
8
|
# The SanitizeHelper module provides a set of methods for scrubbing text of undesired HTML elements.
|
9
9
|
# These helper methods extend Action View making them callable within your template files.
|
10
10
|
module SanitizeHelper
|
11
11
|
extend ActiveSupport::Concern
|
12
|
-
# Sanitizes HTML input, stripping all tags and attributes
|
12
|
+
# Sanitizes HTML input, stripping all but known-safe tags and attributes.
|
13
13
|
#
|
14
14
|
# It also strips href/src attributes with unsafe protocols like
|
15
15
|
# <tt>javascript:</tt>, while also protecting against attempts to use Unicode,
|
16
16
|
# ASCII, and hex character references to work around these protocol filters.
|
17
|
+
# All special characters will be escaped.
|
17
18
|
#
|
18
|
-
# The default sanitizer is Rails::Html::
|
19
|
+
# The default sanitizer is Rails::Html::SafeListSanitizer. See {Rails HTML
|
19
20
|
# Sanitizers}[https://github.com/rails/rails-html-sanitizer] for more information.
|
20
21
|
#
|
21
22
|
# Custom sanitization rules can also be provided.
|
22
23
|
#
|
23
24
|
# Please note that sanitizing user-provided text does not guarantee that the
|
24
|
-
# resulting markup is valid or even well-formed.
|
25
|
-
# contain unescaped characters like <tt><</tt>, <tt>></tt>, or <tt>&</tt>.
|
25
|
+
# resulting markup is valid or even well-formed.
|
26
26
|
#
|
27
27
|
# ==== Options
|
28
28
|
#
|
@@ -39,24 +39,22 @@ module ActionView
|
|
39
39
|
#
|
40
40
|
# <%= sanitize @comment.body %>
|
41
41
|
#
|
42
|
-
# Providing custom
|
42
|
+
# Providing custom lists of permitted tags and attributes:
|
43
43
|
#
|
44
44
|
# <%= sanitize @comment.body, tags: %w(strong em a), attributes: %w(href) %>
|
45
45
|
#
|
46
46
|
# Providing a custom Rails::Html scrubber:
|
47
47
|
#
|
48
48
|
# class CommentScrubber < Rails::Html::PermitScrubber
|
49
|
-
# def
|
50
|
-
#
|
49
|
+
# def initialize
|
50
|
+
# super
|
51
|
+
# self.tags = %w( form script comment blockquote )
|
52
|
+
# self.attributes = %w( style )
|
51
53
|
# end
|
52
54
|
#
|
53
55
|
# def skip_node?(node)
|
54
56
|
# node.text?
|
55
57
|
# end
|
56
|
-
#
|
57
|
-
# def scrub_attribute?(name)
|
58
|
-
# name == 'style'
|
59
|
-
# end
|
60
58
|
# end
|
61
59
|
#
|
62
60
|
# <%= sanitize @comment.body, scrubber: CommentScrubber.new %>
|
@@ -81,15 +79,15 @@ module ActionView
|
|
81
79
|
# config.action_view.sanitized_allowed_tags = ['strong', 'em', 'a']
|
82
80
|
# config.action_view.sanitized_allowed_attributes = ['href', 'title']
|
83
81
|
def sanitize(html, options = {})
|
84
|
-
self.class.
|
82
|
+
self.class.safe_list_sanitizer.sanitize(html, options)&.html_safe
|
85
83
|
end
|
86
84
|
|
87
85
|
# Sanitizes a block of CSS code. Used by +sanitize+ when it comes across a style attribute.
|
88
86
|
def sanitize_css(style)
|
89
|
-
self.class.
|
87
|
+
self.class.safe_list_sanitizer.sanitize_css(style)
|
90
88
|
end
|
91
89
|
|
92
|
-
# Strips all HTML tags from +html+, including comments.
|
90
|
+
# Strips all HTML tags from +html+, including comments and special characters.
|
93
91
|
#
|
94
92
|
# strip_tags("Strip <i>these</i> tags!")
|
95
93
|
# # => Strip these tags!
|
@@ -99,8 +97,11 @@ module ActionView
|
|
99
97
|
#
|
100
98
|
# strip_tags("<div id='top-bar'>Welcome to my website!</div>")
|
101
99
|
# # => Welcome to my website!
|
100
|
+
#
|
101
|
+
# strip_tags("> A quote from Smith & Wesson")
|
102
|
+
# # => > A quote from Smith & Wesson
|
102
103
|
def strip_tags(html)
|
103
|
-
self.class.full_sanitizer.sanitize(html
|
104
|
+
self.class.full_sanitizer.sanitize(html)
|
104
105
|
end
|
105
106
|
|
106
107
|
# Strips all link tags from +html+ leaving just the link text.
|
@@ -113,25 +114,26 @@ module ActionView
|
|
113
114
|
#
|
114
115
|
# strip_links('Blog: <a href="http://www.myblog.com/" class="nav" target=\"_blank\">Visit</a>.')
|
115
116
|
# # => Blog: Visit.
|
117
|
+
#
|
118
|
+
# strip_links('<<a href="https://example.org">malformed & link</a>')
|
119
|
+
# # => <malformed & link
|
116
120
|
def strip_links(html)
|
117
121
|
self.class.link_sanitizer.sanitize(html)
|
118
122
|
end
|
119
123
|
|
120
124
|
module ClassMethods #:nodoc:
|
121
|
-
attr_writer :full_sanitizer, :link_sanitizer, :
|
125
|
+
attr_writer :full_sanitizer, :link_sanitizer, :safe_list_sanitizer
|
122
126
|
|
123
|
-
# Vendors the full, link and white list sanitizers.
|
124
|
-
# Provided strictly for compabitility and can be removed in Rails 5.
|
125
127
|
def sanitizer_vendor
|
126
128
|
Rails::Html::Sanitizer
|
127
129
|
end
|
128
130
|
|
129
131
|
def sanitized_allowed_tags
|
130
|
-
sanitizer_vendor.
|
132
|
+
sanitizer_vendor.safe_list_sanitizer.allowed_tags
|
131
133
|
end
|
132
134
|
|
133
135
|
def sanitized_allowed_attributes
|
134
|
-
sanitizer_vendor.
|
136
|
+
sanitizer_vendor.safe_list_sanitizer.allowed_attributes
|
135
137
|
end
|
136
138
|
|
137
139
|
# Gets the Rails::Html::FullSanitizer instance used by +strip_tags+. Replace with
|
@@ -140,7 +142,6 @@ module ActionView
|
|
140
142
|
# class Application < Rails::Application
|
141
143
|
# config.action_view.full_sanitizer = MySpecialSanitizer.new
|
142
144
|
# end
|
143
|
-
#
|
144
145
|
def full_sanitizer
|
145
146
|
@full_sanitizer ||= sanitizer_vendor.full_sanitizer.new
|
146
147
|
end
|
@@ -151,20 +152,18 @@ module ActionView
|
|
151
152
|
# class Application < Rails::Application
|
152
153
|
# config.action_view.link_sanitizer = MySpecialSanitizer.new
|
153
154
|
# end
|
154
|
-
#
|
155
155
|
def link_sanitizer
|
156
156
|
@link_sanitizer ||= sanitizer_vendor.link_sanitizer.new
|
157
157
|
end
|
158
158
|
|
159
|
-
# Gets the Rails::Html::
|
159
|
+
# Gets the Rails::Html::SafeListSanitizer instance used by sanitize and +sanitize_css+.
|
160
160
|
# Replace with any object that responds to +sanitize+.
|
161
161
|
#
|
162
162
|
# class Application < Rails::Application
|
163
|
-
# config.action_view.
|
163
|
+
# config.action_view.safe_list_sanitizer = MySpecialSanitizer.new
|
164
164
|
# end
|
165
|
-
|
166
|
-
|
167
|
-
@white_list_sanitizer ||= sanitizer_vendor.white_list_sanitizer.new
|
165
|
+
def safe_list_sanitizer
|
166
|
+
@safe_list_sanitizer ||= sanitizer_vendor.safe_list_sanitizer.new
|
168
167
|
end
|
169
168
|
end
|
170
169
|
end
|