actionview 5.2.8.1 → 6.0.6.1
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 +280 -94
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -3
- data/lib/action_view/base.rb +108 -11
- data/lib/action_view/buffers.rb +15 -0
- data/lib/action_view/cache_expiry.rb +53 -0
- data/lib/action_view/context.rb +5 -9
- data/lib/action_view/digestor.rb +12 -20
- data/lib/action_view/flows.rb +0 -1
- data/lib/action_view/gem_version.rb +3 -3
- data/lib/action_view/helpers/active_model_helper.rb +0 -1
- data/lib/action_view/helpers/asset_tag_helper.rb +8 -31
- data/lib/action_view/helpers/asset_url_helper.rb +4 -3
- data/lib/action_view/helpers/cache_helper.rb +19 -12
- data/lib/action_view/helpers/capture_helper.rb +4 -0
- data/lib/action_view/helpers/csp_helper.rb +4 -2
- data/lib/action_view/helpers/csrf_helper.rb +1 -1
- data/lib/action_view/helpers/date_helper.rb +70 -27
- data/lib/action_view/helpers/form_helper.rb +240 -8
- data/lib/action_view/helpers/form_options_helper.rb +27 -18
- data/lib/action_view/helpers/form_tag_helper.rb +17 -15
- data/lib/action_view/helpers/javascript_helper.rb +9 -8
- data/lib/action_view/helpers/number_helper.rb +8 -2
- data/lib/action_view/helpers/output_safety_helper.rb +1 -1
- data/lib/action_view/helpers/rendering_helper.rb +6 -4
- data/lib/action_view/helpers/sanitize_helper.rb +12 -18
- data/lib/action_view/helpers/tag_helper.rb +8 -7
- data/lib/action_view/helpers/tags/base.rb +9 -6
- data/lib/action_view/helpers/tags/check_box.rb +0 -1
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +0 -1
- data/lib/action_view/helpers/tags/collection_helpers.rb +0 -1
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +0 -1
- data/lib/action_view/helpers/tags/color_field.rb +1 -2
- data/lib/action_view/helpers/tags/date_field.rb +0 -1
- data/lib/action_view/helpers/tags/date_select.rb +0 -1
- data/lib/action_view/helpers/tags/datetime_field.rb +0 -1
- data/lib/action_view/helpers/tags/datetime_local_field.rb +0 -1
- data/lib/action_view/helpers/tags/label.rb +0 -1
- data/lib/action_view/helpers/tags/month_field.rb +0 -1
- data/lib/action_view/helpers/tags/radio_button.rb +0 -1
- data/lib/action_view/helpers/tags/select.rb +0 -1
- data/lib/action_view/helpers/tags/text_field.rb +0 -1
- data/lib/action_view/helpers/tags/time_field.rb +0 -1
- data/lib/action_view/helpers/tags/translator.rb +1 -6
- data/lib/action_view/helpers/tags/week_field.rb +0 -1
- data/lib/action_view/helpers/text_helper.rb +3 -4
- data/lib/action_view/helpers/translation_helper.rb +19 -17
- data/lib/action_view/helpers/url_helper.rb +14 -14
- data/lib/action_view/helpers.rb +0 -2
- data/lib/action_view/layouts.rb +5 -8
- data/lib/action_view/log_subscriber.rb +6 -7
- data/lib/action_view/lookup_context.rb +75 -32
- data/lib/action_view/path_set.rb +5 -11
- data/lib/action_view/railtie.rb +24 -1
- data/lib/action_view/record_identifier.rb +2 -3
- data/lib/action_view/renderer/abstract_renderer.rb +56 -4
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +63 -17
- data/lib/action_view/renderer/partial_renderer.rb +67 -57
- data/lib/action_view/renderer/renderer.rb +16 -4
- data/lib/action_view/renderer/streaming_template_renderer.rb +5 -7
- data/lib/action_view/renderer/template_renderer.rb +25 -20
- data/lib/action_view/rendering.rb +51 -32
- data/lib/action_view/routing_url_for.rb +12 -11
- data/lib/action_view/template/error.rb +30 -15
- data/lib/action_view/template/handlers/builder.rb +2 -2
- data/lib/action_view/template/handlers/erb/erubi.rb +7 -3
- data/lib/action_view/template/handlers/erb.rb +17 -8
- data/lib/action_view/template/handlers/html.rb +1 -1
- data/lib/action_view/template/handlers/raw.rb +2 -2
- data/lib/action_view/template/handlers.rb +27 -1
- data/lib/action_view/template/html.rb +14 -5
- 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 +134 -135
- 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 +5 -3
- data/lib/action_view/template.rb +102 -71
- data/lib/action_view/test_case.rb +3 -4
- data/lib/action_view/testing/resolvers.rb +33 -21
- data/lib/action_view/unbound_template.rb +31 -0
- data/lib/action_view/view_paths.rb +25 -2
- data/lib/action_view.rb +4 -2
- data/lib/assets/compiled/rails-ujs.js +30 -4
- metadata +27 -18
- data/lib/action_view/helpers/record_tag_helper.rb +0 -23
data/lib/action_view/base.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require "active_support/core_ext/module/attr_internal"
|
4
4
|
require "active_support/core_ext/module/attribute_accessors"
|
5
5
|
require "active_support/ordered_options"
|
6
|
+
require "active_support/deprecation"
|
6
7
|
require "action_view/log_subscriber"
|
7
8
|
require "action_view/helpers"
|
8
9
|
require "action_view/context"
|
@@ -151,7 +152,7 @@ module ActionView #:nodoc:
|
|
151
152
|
# Specify whether rendering within namespaced controllers should prefix
|
152
153
|
# the partial paths for ActiveModel objects with the namespace.
|
153
154
|
# (e.g., an Admin::PostsController would render @post using /admin/posts/_post.erb)
|
154
|
-
|
155
|
+
class_attribute :prefix_partial_path_with_controller_namespace, default: true
|
155
156
|
|
156
157
|
# Specify default_formats that can be rendered.
|
157
158
|
cattr_accessor :default_formats
|
@@ -179,37 +180,133 @@ module ActionView #:nodoc:
|
|
179
180
|
def xss_safe? #:nodoc:
|
180
181
|
true
|
181
182
|
end
|
183
|
+
|
184
|
+
def with_empty_template_cache # :nodoc:
|
185
|
+
subclass = Class.new(self) {
|
186
|
+
# We can't implement these as self.class because subclasses will
|
187
|
+
# share the same template cache as superclasses, so "changed?" won't work
|
188
|
+
# correctly.
|
189
|
+
define_method(:compiled_method_container) { subclass }
|
190
|
+
define_singleton_method(:compiled_method_container) { subclass }
|
191
|
+
}
|
192
|
+
end
|
193
|
+
|
194
|
+
def changed?(other) # :nodoc:
|
195
|
+
compiled_method_container != other.compiled_method_container
|
196
|
+
end
|
182
197
|
end
|
183
198
|
|
184
|
-
|
199
|
+
attr_reader :view_renderer, :lookup_context
|
185
200
|
attr_internal :config, :assigns
|
186
201
|
|
187
|
-
delegate :lookup_context, to: :view_renderer
|
188
202
|
delegate :formats, :formats=, :locale, :locale=, :view_paths, :view_paths=, to: :lookup_context
|
189
203
|
|
190
204
|
def assign(new_assigns) # :nodoc:
|
191
205
|
@_assigns = new_assigns.each { |key, value| instance_variable_set("@#{key}", value) }
|
192
206
|
end
|
193
207
|
|
194
|
-
|
208
|
+
# :stopdoc:
|
209
|
+
|
210
|
+
def self.build_lookup_context(context)
|
211
|
+
case context
|
212
|
+
when ActionView::Renderer
|
213
|
+
context.lookup_context
|
214
|
+
when Array
|
215
|
+
ActionView::LookupContext.new(context)
|
216
|
+
when ActionView::PathSet
|
217
|
+
ActionView::LookupContext.new(context)
|
218
|
+
when nil
|
219
|
+
ActionView::LookupContext.new([])
|
220
|
+
else
|
221
|
+
raise NotImplementedError, context.class.name
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def self.empty
|
226
|
+
with_view_paths([])
|
227
|
+
end
|
228
|
+
|
229
|
+
def self.with_view_paths(view_paths, assigns = {}, controller = nil)
|
230
|
+
with_context ActionView::LookupContext.new(view_paths), assigns, controller
|
231
|
+
end
|
232
|
+
|
233
|
+
def self.with_context(context, assigns = {}, controller = nil)
|
234
|
+
new context, assigns, controller
|
235
|
+
end
|
236
|
+
|
237
|
+
NULL = Object.new
|
238
|
+
|
239
|
+
# :startdoc:
|
240
|
+
|
241
|
+
def initialize(lookup_context = nil, assigns = {}, controller = nil, formats = NULL) #:nodoc:
|
195
242
|
@_config = ActiveSupport::InheritableOptions.new
|
196
243
|
|
197
|
-
|
198
|
-
|
244
|
+
unless formats == NULL
|
245
|
+
ActiveSupport::Deprecation.warn <<~eowarn.squish
|
246
|
+
Passing formats to ActionView::Base.new is deprecated
|
247
|
+
eowarn
|
248
|
+
end
|
249
|
+
|
250
|
+
case lookup_context
|
251
|
+
when ActionView::LookupContext
|
252
|
+
@lookup_context = lookup_context
|
199
253
|
else
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
@
|
254
|
+
ActiveSupport::Deprecation.warn <<~eowarn.squish
|
255
|
+
ActionView::Base instances should be constructed with a lookup context,
|
256
|
+
assignments, and a controller.
|
257
|
+
eowarn
|
258
|
+
@lookup_context = self.class.build_lookup_context(lookup_context)
|
205
259
|
end
|
206
260
|
|
261
|
+
@view_renderer = ActionView::Renderer.new @lookup_context
|
262
|
+
@current_template = nil
|
263
|
+
|
207
264
|
@cache_hit = {}
|
208
265
|
assign(assigns)
|
209
266
|
assign_controller(controller)
|
210
267
|
_prepare_context
|
211
268
|
end
|
212
269
|
|
270
|
+
def _run(method, template, locals, buffer, &block)
|
271
|
+
_old_output_buffer, _old_virtual_path, _old_template = @output_buffer, @virtual_path, @current_template
|
272
|
+
@current_template = template
|
273
|
+
@output_buffer = buffer
|
274
|
+
send(method, locals, buffer, &block)
|
275
|
+
ensure
|
276
|
+
@output_buffer, @virtual_path, @current_template = _old_output_buffer, _old_virtual_path, _old_template
|
277
|
+
end
|
278
|
+
|
279
|
+
def compiled_method_container
|
280
|
+
if self.class == ActionView::Base
|
281
|
+
ActiveSupport::Deprecation.warn <<~eowarn.squish
|
282
|
+
ActionView::Base instances must implement `compiled_method_container`
|
283
|
+
or use the class method `with_empty_template_cache` for constructing
|
284
|
+
an ActionView::Base instance that has an empty cache.
|
285
|
+
eowarn
|
286
|
+
end
|
287
|
+
|
288
|
+
self.class
|
289
|
+
end
|
290
|
+
|
291
|
+
def in_rendering_context(options)
|
292
|
+
old_view_renderer = @view_renderer
|
293
|
+
old_lookup_context = @lookup_context
|
294
|
+
|
295
|
+
if !lookup_context.html_fallback_for_js && options[:formats]
|
296
|
+
formats = Array(options[:formats])
|
297
|
+
if formats == [:js]
|
298
|
+
formats << :html
|
299
|
+
end
|
300
|
+
@lookup_context = lookup_context.with_prepended_formats(formats)
|
301
|
+
@view_renderer = ActionView::Renderer.new @lookup_context
|
302
|
+
end
|
303
|
+
|
304
|
+
yield @view_renderer
|
305
|
+
ensure
|
306
|
+
@view_renderer = old_view_renderer
|
307
|
+
@lookup_context = old_lookup_context
|
308
|
+
end
|
309
|
+
|
213
310
|
ActiveSupport.run_load_hooks(:action_view, self)
|
214
311
|
end
|
215
312
|
end
|
data/lib/action_view/buffers.rb
CHANGED
@@ -3,6 +3,21 @@
|
|
3
3
|
require "active_support/core_ext/string/output_safety"
|
4
4
|
|
5
5
|
module ActionView
|
6
|
+
# Used as a buffer for views
|
7
|
+
#
|
8
|
+
# The main difference between this and ActiveSupport::SafeBuffer
|
9
|
+
# is for the methods `<<` and `safe_expr_append=` the inputs are
|
10
|
+
# checked for nil before they are assigned and `to_s` is called on
|
11
|
+
# the input. For example:
|
12
|
+
#
|
13
|
+
# obuf = ActionView::OutputBuffer.new "hello"
|
14
|
+
# obuf << 5
|
15
|
+
# puts obuf # => "hello5"
|
16
|
+
#
|
17
|
+
# sbuf = ActiveSupport::SafeBuffer.new "hello"
|
18
|
+
# sbuf << 5
|
19
|
+
# puts sbuf # => "hello\u0005"
|
20
|
+
#
|
6
21
|
class OutputBuffer < ActiveSupport::SafeBuffer #:nodoc:
|
7
22
|
def initialize(*)
|
8
23
|
super
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionView
|
4
|
+
class CacheExpiry
|
5
|
+
class Executor
|
6
|
+
def initialize(watcher:)
|
7
|
+
@cache_expiry = CacheExpiry.new(watcher: watcher)
|
8
|
+
end
|
9
|
+
|
10
|
+
def before(target)
|
11
|
+
@cache_expiry.clear_cache_if_necessary
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(watcher:)
|
16
|
+
@watched_dirs = nil
|
17
|
+
@watcher_class = watcher
|
18
|
+
@watcher = nil
|
19
|
+
@mutex = Mutex.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def clear_cache_if_necessary
|
23
|
+
@mutex.synchronize do
|
24
|
+
watched_dirs = dirs_to_watch
|
25
|
+
return if watched_dirs.empty?
|
26
|
+
|
27
|
+
if watched_dirs != @watched_dirs
|
28
|
+
@watched_dirs = watched_dirs
|
29
|
+
@watcher = @watcher_class.new([], watched_dirs) do
|
30
|
+
clear_cache
|
31
|
+
end
|
32
|
+
@watcher.execute
|
33
|
+
else
|
34
|
+
@watcher.execute_if_updated
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def clear_cache
|
40
|
+
ActionView::LookupContext::DetailsKey.clear
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def dirs_to_watch
|
45
|
+
fs_paths = all_view_paths.grep(FileSystemResolver)
|
46
|
+
fs_paths.map(&:path).sort.uniq
|
47
|
+
end
|
48
|
+
|
49
|
+
def all_view_paths
|
50
|
+
ActionView::ViewPaths.all_view_paths.flat_map(&:paths)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/action_view/context.rb
CHANGED
@@ -1,21 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionView
|
4
|
-
module CompiledTemplates #:nodoc:
|
5
|
-
# holds compiled template code
|
6
|
-
end
|
7
|
-
|
8
4
|
# = Action View Context
|
9
5
|
#
|
10
6
|
# Action View contexts are supplied to Action Controller to render a template.
|
11
7
|
# The default Action View context is ActionView::Base.
|
12
8
|
#
|
13
|
-
# In order to work with
|
14
|
-
# The initialization of the variables used by the context
|
15
|
-
# and @virtual_path) is responsibility of the
|
16
|
-
# (although you can call _prepare_context
|
9
|
+
# In order to work with Action Controller, a Context must just include this
|
10
|
+
# module. The initialization of the variables used by the context
|
11
|
+
# (@output_buffer, @view_flow, and @virtual_path) is responsibility of the
|
12
|
+
# object that includes this module (although you can call _prepare_context
|
13
|
+
# defined below).
|
17
14
|
module Context
|
18
|
-
include CompiledTemplates
|
19
15
|
attr_accessor :output_buffer, :view_flow
|
20
16
|
|
21
17
|
# Prepares the context by setting the appropriate instance variables.
|
data/lib/action_view/digestor.rb
CHANGED
@@ -1,28 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "concurrent/map"
|
4
3
|
require "action_view/dependency_tracker"
|
5
|
-
require "monitor"
|
6
4
|
|
7
5
|
module ActionView
|
8
6
|
class Digestor
|
9
7
|
@@digest_mutex = Mutex.new
|
10
8
|
|
11
|
-
module PerExecutionDigestCacheExpiry
|
12
|
-
def self.before(target)
|
13
|
-
ActionView::LookupContext::DetailsKey.clear
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
9
|
class << self
|
18
10
|
# Supported options:
|
19
11
|
#
|
20
|
-
# * <tt>name</tt>
|
21
|
-
# * <tt>
|
22
|
-
# * <tt>
|
23
|
-
|
24
|
-
|
25
|
-
|
12
|
+
# * <tt>name</tt> - Template name
|
13
|
+
# * <tt>format</tt> - Template format
|
14
|
+
# * <tt>finder</tt> - An instance of <tt>ActionView::LookupContext</tt>
|
15
|
+
# * <tt>dependencies</tt> - An array of dependent views
|
16
|
+
def digest(name:, format: nil, finder:, dependencies: nil)
|
17
|
+
if dependencies.nil? || dependencies.empty?
|
18
|
+
cache_key = "#{name}.#{format}"
|
19
|
+
else
|
20
|
+
cache_key = [ name, format, dependencies ].flatten.compact.join(".")
|
21
|
+
end
|
26
22
|
|
27
23
|
# this is a correctly done double-checked locking idiom
|
28
24
|
# (Concurrent::Map's lookups have volatile semantics)
|
@@ -32,7 +28,7 @@ module ActionView
|
|
32
28
|
root = tree(name, finder, partial)
|
33
29
|
dependencies.each do |injected_dep|
|
34
30
|
root.children << Injected.new(injected_dep, nil, nil)
|
35
|
-
end
|
31
|
+
end if dependencies
|
36
32
|
finder.digest_cache[cache_key] = root.digest(finder)
|
37
33
|
end
|
38
34
|
end
|
@@ -47,8 +43,6 @@ module ActionView
|
|
47
43
|
logical_name = name.gsub(%r|/_|, "/")
|
48
44
|
|
49
45
|
if template = find_template(finder, logical_name, [], partial, [])
|
50
|
-
finder.rendered_format ||= template.formats.first
|
51
|
-
|
52
46
|
if node = seen[template.identifier] # handle cycles in the tree
|
53
47
|
node
|
54
48
|
else
|
@@ -72,9 +66,7 @@ module ActionView
|
|
72
66
|
private
|
73
67
|
def find_template(finder, name, prefixes, partial, keys)
|
74
68
|
finder.disable_cache do
|
75
|
-
|
76
|
-
result = finder.find_all(name, prefixes, partial, keys, formats: [format]).first if format
|
77
|
-
result || finder.find_all(name, prefixes, partial, keys).first
|
69
|
+
finder.find_all(name, prefixes, partial, keys).first
|
78
70
|
end
|
79
71
|
end
|
80
72
|
end
|
data/lib/action_view/flows.rb
CHANGED
@@ -55,7 +55,7 @@ module ActionView
|
|
55
55
|
# that path.
|
56
56
|
# * <tt>:skip_pipeline</tt> - This option is used to bypass the asset pipeline
|
57
57
|
# when it is set to true.
|
58
|
-
# * <tt>:nonce
|
58
|
+
# * <tt>:nonce</tt> - When set to true, adds an automatic nonce value if
|
59
59
|
# you have Content Security Policy enabled.
|
60
60
|
#
|
61
61
|
# ==== Examples
|
@@ -98,7 +98,7 @@ module ActionView
|
|
98
98
|
if tag_options["nonce"] == true
|
99
99
|
tag_options["nonce"] = content_security_policy_nonce
|
100
100
|
end
|
101
|
-
content_tag("script"
|
101
|
+
content_tag("script", "", tag_options)
|
102
102
|
}.join("\n").html_safe
|
103
103
|
|
104
104
|
request.send_early_hints("Link" => early_hints_links.join("\n")) if respond_to?(:request) && request
|
@@ -274,7 +274,7 @@ module ActionView
|
|
274
274
|
crossorigin = "anonymous" if crossorigin == true || (crossorigin.blank? && as_type == "font")
|
275
275
|
nopush = options.delete(:nopush) || false
|
276
276
|
|
277
|
-
link_tag = tag.link({
|
277
|
+
link_tag = tag.link(**{
|
278
278
|
rel: "preload",
|
279
279
|
href: href,
|
280
280
|
as: as_type,
|
@@ -329,14 +329,14 @@ module ActionView
|
|
329
329
|
# image_tag("pic.jpg", srcset: [["pic_1024.jpg", "1024w"], ["pic_1980.jpg", "1980w"]], sizes: "100vw")
|
330
330
|
# # => <img src="/assets/pic.jpg" srcset="/assets/pic_1024.jpg 1024w, /assets/pic_1980.jpg 1980w" sizes="100vw">
|
331
331
|
#
|
332
|
-
# Active Storage (images that are uploaded by the users of your app):
|
332
|
+
# Active Storage blobs (images that are uploaded by the users of your app):
|
333
333
|
#
|
334
334
|
# image_tag(user.avatar)
|
335
335
|
# # => <img src="/rails/active_storage/blobs/.../tiger.jpg" />
|
336
|
-
# image_tag(user.avatar.variant(
|
337
|
-
# # => <img src="/rails/active_storage/
|
338
|
-
# image_tag(user.avatar.variant(
|
339
|
-
# # => <img width="100" height="100" src="/rails/active_storage/
|
336
|
+
# image_tag(user.avatar.variant(resize_to_limit: [100, 100]))
|
337
|
+
# # => <img src="/rails/active_storage/representations/.../tiger.jpg" />
|
338
|
+
# image_tag(user.avatar.variant(resize_to_limit: [100, 100]), size: '100')
|
339
|
+
# # => <img width="100" height="100" src="/rails/active_storage/representations/.../tiger.jpg" />
|
340
340
|
def image_tag(source, options = {})
|
341
341
|
options = options.symbolize_keys
|
342
342
|
check_for_image_tag_errors(options)
|
@@ -355,29 +355,6 @@ module ActionView
|
|
355
355
|
tag("img", options)
|
356
356
|
end
|
357
357
|
|
358
|
-
# Returns a string suitable for an HTML image tag alt attribute.
|
359
|
-
# The +src+ argument is meant to be an image file path.
|
360
|
-
# The method removes the basename of the file path and the digest,
|
361
|
-
# if any. It also removes hyphens and underscores from file names and
|
362
|
-
# replaces them with spaces, returning a space-separated, titleized
|
363
|
-
# string.
|
364
|
-
#
|
365
|
-
# ==== Examples
|
366
|
-
#
|
367
|
-
# image_alt('rails.png')
|
368
|
-
# # => Rails
|
369
|
-
#
|
370
|
-
# image_alt('hyphenated-file-name.png')
|
371
|
-
# # => Hyphenated file name
|
372
|
-
#
|
373
|
-
# image_alt('underscored_file_name.png')
|
374
|
-
# # => Underscored file name
|
375
|
-
def image_alt(src)
|
376
|
-
ActiveSupport::Deprecation.warn("image_alt is deprecated and will be removed from Rails 6.0. You must explicitly set alt text on images.")
|
377
|
-
|
378
|
-
File.basename(src, ".*".freeze).sub(/-[[:xdigit:]]{32,64}\z/, "".freeze).tr("-_".freeze, " ".freeze).capitalize
|
379
|
-
end
|
380
|
-
|
381
358
|
# Returns an HTML video tag for the +sources+. If +sources+ is a string,
|
382
359
|
# a single video tag will be returned. If +sources+ is an array, a video
|
383
360
|
# tag with nested source tags for each source will be returned. The
|
@@ -98,8 +98,9 @@ module ActionView
|
|
98
98
|
# have SSL certificates for each of the asset hosts this technique allows you
|
99
99
|
# to avoid warnings in the client about mixed media.
|
100
100
|
# Note that the +request+ parameter might not be supplied, e.g. when the assets
|
101
|
-
# are precompiled
|
102
|
-
# since a +Proc+ allows missing parameters and sets them
|
101
|
+
# are precompiled with the command `rails assets:precompile`. Make sure to use a
|
102
|
+
# +Proc+ instead of a lambda, since a +Proc+ allows missing parameters and sets them
|
103
|
+
# to +nil+.
|
103
104
|
#
|
104
105
|
# config.action_controller.asset_host = Proc.new { |source, request|
|
105
106
|
# if request && request.ssl?
|
@@ -187,7 +188,7 @@ module ActionView
|
|
187
188
|
return "" if source.blank?
|
188
189
|
return source if URI_REGEXP.match?(source)
|
189
190
|
|
190
|
-
tail, source = source[/([\?#].+)$/], source.sub(/([\?#].+)$/, ""
|
191
|
+
tail, source = source[/([\?#].+)$/], source.sub(/([\?#].+)$/, "")
|
191
192
|
|
192
193
|
if extname = compute_asset_extname(source, options)
|
193
194
|
source = "#{source}#{extname}"
|
@@ -166,7 +166,7 @@ module ActionView
|
|
166
166
|
def cache(name = {}, options = {}, &block)
|
167
167
|
if controller.respond_to?(:perform_caching) && controller.perform_caching
|
168
168
|
name_options = options.slice(:skip_digest, :virtual_path)
|
169
|
-
safe_concat(fragment_for(cache_fragment_name(name, name_options), options, &block))
|
169
|
+
safe_concat(fragment_for(cache_fragment_name(name, **name_options), options, &block))
|
170
170
|
else
|
171
171
|
yield
|
172
172
|
end
|
@@ -201,34 +201,41 @@ module ActionView
|
|
201
201
|
end
|
202
202
|
|
203
203
|
# This helper returns the name of a cache key for a given fragment cache
|
204
|
-
# call. By supplying
|
204
|
+
# call. By supplying <tt>skip_digest: true</tt> to cache, the digestion of cache
|
205
205
|
# fragments can be manually bypassed. This is useful when cache fragments
|
206
206
|
# cannot be manually expired unless you know the exact key which is the
|
207
207
|
# case when using memcached.
|
208
208
|
#
|
209
209
|
# The digest will be generated using +virtual_path:+ if it is provided.
|
210
210
|
#
|
211
|
-
def cache_fragment_name(name = {}, skip_digest: nil, virtual_path: nil)
|
211
|
+
def cache_fragment_name(name = {}, skip_digest: nil, virtual_path: nil, digest_path: nil)
|
212
212
|
if skip_digest
|
213
213
|
name
|
214
214
|
else
|
215
|
-
fragment_name_with_digest(name, virtual_path)
|
215
|
+
fragment_name_with_digest(name, virtual_path, digest_path)
|
216
216
|
end
|
217
217
|
end
|
218
218
|
|
219
|
-
|
219
|
+
def digest_path_from_template(template) # :nodoc:
|
220
|
+
digest = Digestor.digest(name: template.virtual_path, format: template.format, finder: lookup_context, dependencies: view_cache_dependencies)
|
220
221
|
|
221
|
-
|
222
|
+
if digest.present?
|
223
|
+
"#{template.virtual_path}:#{digest}"
|
224
|
+
else
|
225
|
+
template.virtual_path
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
private
|
230
|
+
def fragment_name_with_digest(name, virtual_path, digest_path)
|
222
231
|
virtual_path ||= @virtual_path
|
223
232
|
|
224
|
-
if virtual_path
|
233
|
+
if virtual_path || digest_path
|
225
234
|
name = controller.url_for(name).split("://").last if name.is_a?(Hash)
|
226
235
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
[ virtual_path, name ]
|
231
|
-
end
|
236
|
+
digest_path ||= digest_path_from_template(@current_template)
|
237
|
+
|
238
|
+
[ digest_path, name ]
|
232
239
|
else
|
233
240
|
name
|
234
241
|
end
|
@@ -36,6 +36,10 @@ module ActionView
|
|
36
36
|
# </body>
|
37
37
|
# </html>
|
38
38
|
#
|
39
|
+
# The return of capture is the string generated by the block. For Example:
|
40
|
+
#
|
41
|
+
# @greeting # => "Welcome to my shiny new web page! The date and time is 2018-09-06 11:09:16 -0500"
|
42
|
+
#
|
39
43
|
def capture(*args)
|
40
44
|
value = nil
|
41
45
|
buffer = with_output_buffer { value = yield(*args) }
|
@@ -14,9 +14,11 @@ module ActionView
|
|
14
14
|
# This is used by the Rails UJS helper to create dynamically
|
15
15
|
# loaded inline <script> elements.
|
16
16
|
#
|
17
|
-
def csp_meta_tag
|
17
|
+
def csp_meta_tag(**options)
|
18
18
|
if content_security_policy?
|
19
|
-
|
19
|
+
options[:name] = "csp-nonce"
|
20
|
+
options[:content] = content_security_policy_nonce
|
21
|
+
tag("meta", options)
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|
@@ -20,7 +20,7 @@ module ActionView
|
|
20
20
|
# "X-CSRF-Token" HTTP header. If you are using rails-ujs this happens automatically.
|
21
21
|
#
|
22
22
|
def csrf_meta_tags
|
23
|
-
if protect_against_forgery?
|
23
|
+
if defined?(protect_against_forgery?) && protect_against_forgery?
|
24
24
|
[
|
25
25
|
tag("meta", name: "csrf-param", content: request_forgery_protection_token),
|
26
26
|
tag("meta", name: "csrf-token", content: form_authenticity_token)
|