actionview 4.2.11.1 → 7.0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of actionview might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +229 -215
- data/MIT-LICENSE +1 -1
- data/README.rdoc +9 -8
- data/lib/action_view/base.rb +116 -43
- data/lib/action_view/buffers.rb +20 -3
- data/lib/action_view/cache_expiry.rb +66 -0
- data/lib/action_view/context.rb +8 -12
- data/lib/action_view/dependency_tracker/erb_tracker.rb +154 -0
- data/lib/action_view/dependency_tracker/ripper_tracker.rb +59 -0
- data/lib/action_view/dependency_tracker.rb +21 -122
- data/lib/action_view/digestor.rb +92 -85
- data/lib/action_view/flows.rb +15 -16
- data/lib/action_view/gem_version.rb +6 -4
- data/lib/action_view/helpers/active_model_helper.rb +17 -12
- data/lib/action_view/helpers/asset_tag_helper.rb +356 -101
- data/lib/action_view/helpers/asset_url_helper.rb +180 -74
- data/lib/action_view/helpers/atom_feed_helper.rb +21 -19
- data/lib/action_view/helpers/cache_helper.rb +156 -43
- data/lib/action_view/helpers/capture_helper.rb +21 -14
- data/lib/action_view/helpers/controller_helper.rb +16 -5
- 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 +288 -132
- data/lib/action_view/helpers/debug_helper.rb +9 -6
- data/lib/action_view/helpers/form_helper.rb +956 -173
- data/lib/action_view/helpers/form_options_helper.rb +178 -97
- data/lib/action_view/helpers/form_tag_helper.rb +220 -101
- data/lib/action_view/helpers/javascript_helper.rb +33 -19
- data/lib/action_view/helpers/number_helper.rb +88 -63
- data/lib/action_view/helpers/output_safety_helper.rb +38 -6
- data/lib/action_view/helpers/rendering_helper.rb +21 -10
- data/lib/action_view/helpers/sanitize_helper.rb +31 -32
- data/lib/action_view/helpers/tag_helper.rb +332 -71
- data/lib/action_view/helpers/tags/base.rb +123 -99
- data/lib/action_view/helpers/tags/check_box.rb +21 -20
- 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 +5 -3
- 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 +18 -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 +12 -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/weekday_select.rb +28 -0
- data/lib/action_view/helpers/tags.rb +5 -2
- data/lib/action_view/helpers/text_helper.rb +80 -51
- data/lib/action_view/helpers/translation_helper.rb +120 -69
- data/lib/action_view/helpers/url_helper.rb +398 -171
- data/lib/action_view/helpers.rb +29 -27
- data/lib/action_view/layouts.rb +68 -63
- data/lib/action_view/log_subscriber.rb +77 -10
- data/lib/action_view/lookup_context.rb +137 -113
- data/lib/action_view/model_naming.rb +4 -2
- data/lib/action_view/path_set.rb +28 -32
- data/lib/action_view/railtie.rb +74 -13
- data/lib/action_view/record_identifier.rb +53 -26
- data/lib/action_view/render_parser.rb +188 -0
- data/lib/action_view/renderer/abstract_renderer.rb +152 -15
- 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 +51 -333
- data/lib/action_view/renderer/renderer.rb +68 -11
- data/lib/action_view/renderer/streaming_template_renderer.rb +60 -56
- data/lib/action_view/renderer/template_renderer.rb +87 -74
- data/lib/action_view/rendering.rb +73 -47
- data/lib/action_view/ripper_ast_parser.rb +198 -0
- data/lib/action_view/routing_url_for.rb +35 -24
- data/lib/action_view/tasks/cache_digests.rake +25 -0
- data/lib/action_view/template/error.rb +151 -41
- 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 +29 -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 +14 -10
- data/lib/action_view/template/html.rb +12 -13
- 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 +139 -300
- 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 +10 -12
- data/lib/action_view/template/types.rb +28 -26
- data/lib/action_view/template.rb +123 -91
- data/lib/action_view/template_details.rb +66 -0
- data/lib/action_view/template_path.rb +64 -0
- data/lib/action_view/test_case.rb +70 -53
- data/lib/action_view/testing/resolvers.rb +25 -35
- data/lib/action_view/unbound_template.rb +57 -0
- data/lib/action_view/version.rb +3 -1
- data/lib/action_view/view_paths.rb +73 -58
- data/lib/action_view.rb +16 -11
- data/lib/assets/compiled/rails-ujs.js +746 -0
- metadata +52 -32
- data/lib/action_view/helpers/record_tag_helper.rb +0 -108
- data/lib/action_view/tasks/dependencies.rake +0 -23
@@ -1,34 +1,37 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionView
|
4
|
-
module Helpers
|
4
|
+
module Helpers # :nodoc:
|
5
5
|
module JavaScriptHelper
|
6
6
|
JS_ESCAPE_MAP = {
|
7
|
-
|
8
|
-
|
7
|
+
"\\" => "\\\\",
|
8
|
+
"</" => '<\/',
|
9
9
|
"\r\n" => '\n',
|
10
10
|
"\n" => '\n',
|
11
11
|
"\r" => '\n',
|
12
12
|
'"' => '\\"',
|
13
|
-
"'" => "\\'"
|
13
|
+
"'" => "\\'",
|
14
|
+
"`" => "\\`",
|
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").force_encoding(Encoding::UTF_8).encode!] = "
"
|
19
|
+
JS_ESCAPE_MAP[(+"\342\200\251").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
|
-
|
27
|
-
|
28
|
-
|
28
|
+
javascript = javascript.to_s
|
29
|
+
if javascript.empty?
|
30
|
+
result = ""
|
29
31
|
else
|
30
|
-
'
|
32
|
+
result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|\342\200\251|[\n\r"']|[`]|[$])/u, JS_ESCAPE_MAP)
|
31
33
|
end
|
34
|
+
javascript.html_safe? ? result.html_safe : result
|
32
35
|
end
|
33
36
|
|
34
37
|
alias_method :j, :escape_javascript
|
@@ -46,10 +49,10 @@ module ActionView
|
|
46
49
|
# +html_options+ may be a hash of attributes for the <tt>\<script></tt>
|
47
50
|
# tag.
|
48
51
|
#
|
49
|
-
# javascript_tag "alert('All is good')",
|
50
|
-
#
|
51
|
-
# Returns:
|
52
|
-
# <script
|
52
|
+
# javascript_tag "alert('All is good')", type: 'application/javascript'
|
53
|
+
#
|
54
|
+
# Returns:
|
55
|
+
# <script type="application/javascript">
|
53
56
|
# //<![CDATA[
|
54
57
|
# alert('All is good')
|
55
58
|
# //]]>
|
@@ -58,7 +61,14 @@ module ActionView
|
|
58
61
|
# Instead of passing the content as an argument, you can also use a block
|
59
62
|
# in which case, you pass your +html_options+ as the first parameter.
|
60
63
|
#
|
61
|
-
# <%= javascript_tag
|
64
|
+
# <%= javascript_tag type: 'application/javascript' do -%>
|
65
|
+
# alert('All is good')
|
66
|
+
# <% end -%>
|
67
|
+
#
|
68
|
+
# If you have a content security policy enabled then you can add an automatic
|
69
|
+
# nonce value by passing <tt>nonce: true</tt> as part of +html_options+. Example:
|
70
|
+
#
|
71
|
+
# <%= javascript_tag nonce: true do -%>
|
62
72
|
# alert('All is good')
|
63
73
|
# <% end -%>
|
64
74
|
def javascript_tag(content_or_options_with_block = nil, html_options = {}, &block)
|
@@ -70,10 +80,14 @@ module ActionView
|
|
70
80
|
content_or_options_with_block
|
71
81
|
end
|
72
82
|
|
73
|
-
|
83
|
+
if html_options[:nonce] == true
|
84
|
+
html_options[:nonce] = content_security_policy_nonce
|
85
|
+
end
|
86
|
+
|
87
|
+
content_tag("script", javascript_cdata_section(content), html_options)
|
74
88
|
end
|
75
89
|
|
76
|
-
def javascript_cdata_section(content)
|
90
|
+
def javascript_cdata_section(content) # :nodoc:
|
77
91
|
"\n//#{cdata_section("\n#{content}\n//")}\n".html_safe
|
78
92
|
end
|
79
93
|
end
|
@@ -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
|
-
module Helpers
|
10
|
-
|
9
|
+
module Helpers # :nodoc:
|
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 ".").
|
@@ -227,7 +253,7 @@ module ActionView
|
|
227
253
|
end
|
228
254
|
|
229
255
|
# Formats the bytes in +number+ into a more understandable
|
230
|
-
# representation (e.g., giving it 1500 yields 1.
|
256
|
+
# representation (e.g., giving it 1500 yields 1.46 KB). This
|
231
257
|
# method is useful for reporting file sizes to users. You can
|
232
258
|
# customize the format in the +options+ hash.
|
233
259
|
#
|
@@ -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
|
@@ -273,15 +299,15 @@ module ActionView
|
|
273
299
|
end
|
274
300
|
|
275
301
|
# Pretty prints (formats and approximates) a number in a way it
|
276
|
-
# is more readable by humans (
|
302
|
+
# is more readable by humans (e.g.: 1200000000 becomes "1.2
|
277
303
|
# Billion"). This is useful for numbers that can get very large
|
278
304
|
# (and too hard to read).
|
279
305
|
#
|
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
|
284
|
-
# to use other decimal units (
|
309
|
+
# You can also define your own unit-quantifier names if you want
|
310
|
+
# to use other decimal units (e.g.: 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
|
287
313
|
# (centi, deci, mili, etc).
|
@@ -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
|
+
units.transform_values do |v|
|
429
|
+
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
|
+
result = Float(number, exception: false)
|
452
|
+
raise InvalidNumberError, number if result.nil? && raise_error
|
453
|
+
result
|
454
|
+
end
|
430
455
|
end
|
431
456
|
end
|
432
457
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "active_support/core_ext/string/output_safety"
|
4
|
+
|
5
|
+
module ActionView # :nodoc:
|
4
6
|
# = Action View Raw Output Helper
|
5
|
-
module Helpers
|
7
|
+
module Helpers # :nodoc:
|
6
8
|
module OutputSafetyHelper
|
7
9
|
# This method outputs without escaping a string. Since escaping tags is
|
8
10
|
# now default, this can be used when you don't want Rails to automatically
|
@@ -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,28 +13,37 @@ 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
|
-
# If no options hash is passed or
|
25
|
-
#
|
25
|
+
# If no <tt>options</tt> hash is passed or if <tt>:update</tt> is specified, then:
|
26
|
+
#
|
27
|
+
# If an object responding to +render_in+ is passed, +render_in+ is called on the object,
|
28
|
+
# passing in the current view context.
|
29
|
+
#
|
30
|
+
# Otherwise, a partial is rendered using the second parameter as the locals hash.
|
26
31
|
def render(options = {}, locals = {}, &block)
|
27
32
|
case options
|
28
33
|
when Hash
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
34
|
+
in_rendering_context(options) do |renderer|
|
35
|
+
if block_given?
|
36
|
+
view_renderer.render_partial(self, options.merge(partial: options[:layout]), &block)
|
37
|
+
else
|
38
|
+
view_renderer.render(self, options)
|
39
|
+
end
|
33
40
|
end
|
34
41
|
else
|
35
|
-
|
42
|
+
if options.respond_to?(:render_in)
|
43
|
+
options.render_in(self, &block)
|
44
|
+
else
|
45
|
+
view_renderer.render_partial(self, partial: options, locals: locals, &block)
|
46
|
+
end
|
36
47
|
end
|
37
48
|
end
|
38
49
|
|