actionview 6.0.6.1 → 6.1.7.6
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +248 -220
- data/MIT-LICENSE +1 -2
- data/lib/action_view/base.rb +18 -49
- data/lib/action_view/cache_expiry.rb +1 -2
- data/lib/action_view/dependency_tracker.rb +10 -4
- data/lib/action_view/digestor.rb +3 -2
- data/lib/action_view/gem_version.rb +3 -3
- data/lib/action_view/helpers/asset_tag_helper.rb +57 -17
- data/lib/action_view/helpers/asset_url_helper.rb +6 -4
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -1
- data/lib/action_view/helpers/cache_helper.rb +10 -16
- data/lib/action_view/helpers/date_helper.rb +6 -5
- data/lib/action_view/helpers/form_helper.rb +66 -30
- data/lib/action_view/helpers/form_options_helper.rb +7 -16
- data/lib/action_view/helpers/form_tag_helper.rb +4 -3
- data/lib/action_view/helpers/javascript_helper.rb +3 -3
- data/lib/action_view/helpers/number_helper.rb +6 -6
- data/lib/action_view/helpers/rendering_helper.rb +11 -3
- data/lib/action_view/helpers/tag_helper.rb +98 -22
- data/lib/action_view/helpers/tags/base.rb +10 -6
- data/lib/action_view/helpers/tags/check_box.rb +1 -1
- data/lib/action_view/helpers/tags/date_field.rb +1 -1
- data/lib/action_view/helpers/tags/date_select.rb +2 -2
- data/lib/action_view/helpers/tags/datetime_local_field.rb +1 -1
- data/lib/action_view/helpers/tags/hidden_field.rb +4 -0
- data/lib/action_view/helpers/tags/label.rb +4 -0
- data/lib/action_view/helpers/tags/month_field.rb +1 -1
- data/lib/action_view/helpers/tags/select.rb +1 -1
- data/lib/action_view/helpers/tags/time_field.rb +1 -1
- data/lib/action_view/helpers/tags/week_field.rb +1 -1
- data/lib/action_view/helpers/text_helper.rb +2 -2
- data/lib/action_view/helpers/translation_helper.rb +88 -50
- data/lib/action_view/helpers/url_helper.rb +136 -24
- data/lib/action_view/layouts.rb +3 -2
- data/lib/action_view/log_subscriber.rb +26 -10
- data/lib/action_view/lookup_context.rb +3 -18
- data/lib/action_view/path_set.rb +0 -3
- data/lib/action_view/railtie.rb +39 -46
- data/lib/action_view/renderer/abstract_renderer.rb +93 -14
- 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 +25 -26
- data/lib/action_view/renderer/partial_renderer.rb +20 -282
- data/lib/action_view/renderer/renderer.rb +44 -1
- data/lib/action_view/renderer/streaming_template_renderer.rb +5 -1
- data/lib/action_view/renderer/template_renderer.rb +15 -12
- data/lib/action_view/rendering.rb +3 -1
- data/lib/action_view/routing_url_for.rb +1 -1
- data/lib/action_view/template/handlers/erb/erubi.rb +9 -7
- data/lib/action_view/template/handlers/erb.rb +10 -14
- data/lib/action_view/template/handlers.rb +0 -26
- data/lib/action_view/template/html.rb +1 -11
- data/lib/action_view/template/raw_file.rb +0 -3
- data/lib/action_view/template/renderable.rb +24 -0
- data/lib/action_view/template/resolver.rb +82 -40
- data/lib/action_view/template/text.rb +0 -3
- data/lib/action_view/template.rb +9 -49
- data/lib/action_view/test_case.rb +18 -25
- data/lib/action_view/testing/resolvers.rb +10 -31
- data/lib/action_view/unbound_template.rb +3 -3
- data/lib/action_view/view_paths.rb +34 -36
- data/lib/action_view.rb +4 -1
- data/lib/assets/compiled/rails-ujs.js +38 -7
- metadata +15 -12
data/MIT-LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2004-
|
1
|
+
Copyright (c) 2004-2022 David Heinemeier Hansson
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
@@ -18,4 +18,3 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
20
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
-
|
data/lib/action_view/base.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
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"
|
7
6
|
require "action_view/log_subscriber"
|
8
7
|
require "action_view/helpers"
|
9
8
|
require "action_view/context"
|
@@ -28,7 +27,7 @@ module ActionView #:nodoc:
|
|
28
27
|
# Name: <%= person.name %><br/>
|
29
28
|
# <% end %>
|
30
29
|
#
|
31
|
-
# The loop is
|
30
|
+
# The loop is set up in regular embedding tags <tt><% %></tt>, and the name is written using the output embedding tag <tt><%= %></tt>. Note that this
|
32
31
|
# is not just a usage suggestion. Regular output functions like print or puts won't work with ERB templates. So this would be wrong:
|
33
32
|
#
|
34
33
|
# <%# WRONG %>
|
@@ -163,6 +162,9 @@ module ActionView #:nodoc:
|
|
163
162
|
# Specify whether submit_tag should automatically disable on click
|
164
163
|
cattr_accessor :automatically_disable_submit_tag, default: true
|
165
164
|
|
165
|
+
# Annotate rendered view with file names
|
166
|
+
cattr_accessor :annotate_rendered_view_with_filenames, default: false
|
167
|
+
|
166
168
|
class_attribute :_routes
|
167
169
|
class_attribute :logger
|
168
170
|
|
@@ -188,6 +190,10 @@ module ActionView #:nodoc:
|
|
188
190
|
# correctly.
|
189
191
|
define_method(:compiled_method_container) { subclass }
|
190
192
|
define_singleton_method(:compiled_method_container) { subclass }
|
193
|
+
|
194
|
+
def inspect
|
195
|
+
"#<ActionView::Base:#{'%#016x' % (object_id << 1)}>"
|
196
|
+
end
|
191
197
|
}
|
192
198
|
end
|
193
199
|
|
@@ -207,21 +213,6 @@ module ActionView #:nodoc:
|
|
207
213
|
|
208
214
|
# :stopdoc:
|
209
215
|
|
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
216
|
def self.empty
|
226
217
|
with_view_paths([])
|
227
218
|
end
|
@@ -234,58 +225,36 @@ module ActionView #:nodoc:
|
|
234
225
|
new context, assigns, controller
|
235
226
|
end
|
236
227
|
|
237
|
-
NULL = Object.new
|
238
|
-
|
239
228
|
# :startdoc:
|
240
229
|
|
241
|
-
def initialize(lookup_context
|
230
|
+
def initialize(lookup_context, assigns, controller) #:nodoc:
|
242
231
|
@_config = ActiveSupport::InheritableOptions.new
|
243
232
|
|
244
|
-
|
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
|
253
|
-
else
|
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)
|
259
|
-
end
|
233
|
+
@lookup_context = lookup_context
|
260
234
|
|
261
235
|
@view_renderer = ActionView::Renderer.new @lookup_context
|
262
236
|
@current_template = nil
|
263
237
|
|
264
|
-
@cache_hit = {}
|
265
238
|
assign(assigns)
|
266
239
|
assign_controller(controller)
|
267
240
|
_prepare_context
|
268
241
|
end
|
269
242
|
|
270
|
-
def _run(method, template, locals, buffer, &block)
|
243
|
+
def _run(method, template, locals, buffer, add_to_stack: true, &block)
|
271
244
|
_old_output_buffer, _old_virtual_path, _old_template = @output_buffer, @virtual_path, @current_template
|
272
|
-
@current_template = template
|
245
|
+
@current_template = template if add_to_stack
|
273
246
|
@output_buffer = buffer
|
274
|
-
|
247
|
+
public_send(method, locals, buffer, &block)
|
275
248
|
ensure
|
276
249
|
@output_buffer, @virtual_path, @current_template = _old_output_buffer, _old_virtual_path, _old_template
|
277
250
|
end
|
278
251
|
|
279
252
|
def compiled_method_container
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
eowarn
|
286
|
-
end
|
287
|
-
|
288
|
-
self.class
|
253
|
+
raise NotImplementedError, <<~msg.squish
|
254
|
+
Subclasses of ActionView::Base must implement `compiled_method_container`
|
255
|
+
or use the class method `with_empty_template_cache` for constructing
|
256
|
+
an ActionView::Base subclass that has an empty cache.
|
257
|
+
msg
|
289
258
|
end
|
290
259
|
|
291
260
|
def in_rendering_context(options)
|
@@ -130,8 +130,9 @@ module ActionView
|
|
130
130
|
|
131
131
|
def add_dependencies(render_dependencies, arguments, pattern)
|
132
132
|
arguments.scan(pattern) do
|
133
|
-
|
134
|
-
|
133
|
+
match = Regexp.last_match
|
134
|
+
add_dynamic_dependency(render_dependencies, match[:dynamic])
|
135
|
+
add_static_dependency(render_dependencies, match[:static], match[:quote])
|
135
136
|
end
|
136
137
|
end
|
137
138
|
|
@@ -141,7 +142,12 @@ module ActionView
|
|
141
142
|
end
|
142
143
|
end
|
143
144
|
|
144
|
-
def add_static_dependency(dependencies, dependency)
|
145
|
+
def add_static_dependency(dependencies, dependency, quote_type)
|
146
|
+
if quote_type == '"'
|
147
|
+
# Ignore if there is interpolation
|
148
|
+
return if dependency.include?('#{')
|
149
|
+
end
|
150
|
+
|
145
151
|
if dependency
|
146
152
|
if dependency.include?("/")
|
147
153
|
dependencies << dependency
|
@@ -164,7 +170,7 @@ module ActionView
|
|
164
170
|
def explicit_dependencies
|
165
171
|
dependencies = source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
|
166
172
|
|
167
|
-
wildcards, explicits = dependencies.partition { |dependency| dependency
|
173
|
+
wildcards, explicits = dependencies.partition { |dependency| dependency.end_with?("*") }
|
168
174
|
|
169
175
|
(explicits + resolve_directories(wildcards)).uniq
|
170
176
|
end
|
data/lib/action_view/digestor.rb
CHANGED
@@ -41,8 +41,9 @@ module ActionView
|
|
41
41
|
# Create a dependency tree for template named +name+.
|
42
42
|
def tree(name, finder, partial = false, seen = {})
|
43
43
|
logical_name = name.gsub(%r|/_|, "/")
|
44
|
+
interpolated = name.include?("#")
|
44
45
|
|
45
|
-
if template = find_template(finder, logical_name, [], partial, [])
|
46
|
+
if !interpolated && (template = find_template(finder, logical_name, [], partial, []))
|
46
47
|
if node = seen[template.identifier] # handle cycles in the tree
|
47
48
|
node
|
48
49
|
else
|
@@ -55,7 +56,7 @@ module ActionView
|
|
55
56
|
node
|
56
57
|
end
|
57
58
|
else
|
58
|
-
unless
|
59
|
+
unless interpolated # Dynamic template partial names can never be tracked
|
59
60
|
logger.error " Couldn't find template for digesting: #{name}"
|
60
61
|
end
|
61
62
|
|
@@ -3,7 +3,6 @@
|
|
3
3
|
require "active_support/core_ext/array/extract_options"
|
4
4
|
require "active_support/core_ext/hash/keys"
|
5
5
|
require "active_support/core_ext/object/inclusion"
|
6
|
-
require "active_support/core_ext/object/try"
|
7
6
|
require "action_view/helpers/asset_url_helper"
|
8
7
|
require "action_view/helpers/tag_helper"
|
9
8
|
|
@@ -24,13 +23,15 @@ module ActionView
|
|
24
23
|
include AssetUrlHelper
|
25
24
|
include TagHelper
|
26
25
|
|
26
|
+
mattr_accessor :preload_links_header
|
27
|
+
|
27
28
|
# Returns an HTML script tag for each of the +sources+ provided.
|
28
29
|
#
|
29
30
|
# Sources may be paths to JavaScript files. Relative paths are assumed to be relative
|
30
31
|
# to <tt>assets/javascripts</tt>, full paths are assumed to be relative to the document
|
31
32
|
# root. Relative paths are idiomatic, use absolute paths only when needed.
|
32
33
|
#
|
33
|
-
# When passing paths, the ".js" extension is optional.
|
34
|
+
# When passing paths, the ".js" extension is optional. If you do not want ".js"
|
34
35
|
# appended to the path <tt>extname: false</tt> can be set on the options.
|
35
36
|
#
|
36
37
|
# You can modify the HTML attributes of the script tag by passing a hash as the
|
@@ -87,13 +88,24 @@ module ActionView
|
|
87
88
|
def javascript_include_tag(*sources)
|
88
89
|
options = sources.extract_options!.stringify_keys
|
89
90
|
path_options = options.extract!("protocol", "extname", "host", "skip_pipeline").symbolize_keys
|
90
|
-
|
91
|
+
preload_links = []
|
92
|
+
nopush = options["nopush"].nil? ? true : options.delete("nopush")
|
93
|
+
crossorigin = options.delete("crossorigin")
|
94
|
+
crossorigin = "anonymous" if crossorigin == true
|
95
|
+
integrity = options["integrity"]
|
91
96
|
|
92
97
|
sources_tags = sources.uniq.map { |source|
|
93
98
|
href = path_to_javascript(source, path_options)
|
94
|
-
|
99
|
+
if preload_links_header && !options["defer"]
|
100
|
+
preload_link = "<#{href}>; rel=preload; as=script"
|
101
|
+
preload_link += "; crossorigin=#{crossorigin}" unless crossorigin.nil?
|
102
|
+
preload_link += "; integrity=#{integrity}" unless integrity.nil?
|
103
|
+
preload_link += "; nopush" if nopush
|
104
|
+
preload_links << preload_link
|
105
|
+
end
|
95
106
|
tag_options = {
|
96
|
-
"src" => href
|
107
|
+
"src" => href,
|
108
|
+
"crossorigin" => crossorigin
|
97
109
|
}.merge!(options)
|
98
110
|
if tag_options["nonce"] == true
|
99
111
|
tag_options["nonce"] = content_security_policy_nonce
|
@@ -101,7 +113,9 @@ module ActionView
|
|
101
113
|
content_tag("script", "", tag_options)
|
102
114
|
}.join("\n").html_safe
|
103
115
|
|
104
|
-
|
116
|
+
if preload_links_header
|
117
|
+
send_preload_links_header(preload_links)
|
118
|
+
end
|
105
119
|
|
106
120
|
sources_tags
|
107
121
|
end
|
@@ -137,20 +151,33 @@ module ActionView
|
|
137
151
|
def stylesheet_link_tag(*sources)
|
138
152
|
options = sources.extract_options!.stringify_keys
|
139
153
|
path_options = options.extract!("protocol", "host", "skip_pipeline").symbolize_keys
|
140
|
-
|
154
|
+
preload_links = []
|
155
|
+
crossorigin = options.delete("crossorigin")
|
156
|
+
crossorigin = "anonymous" if crossorigin == true
|
157
|
+
nopush = options["nopush"].nil? ? true : options.delete("nopush")
|
158
|
+
integrity = options["integrity"]
|
141
159
|
|
142
160
|
sources_tags = sources.uniq.map { |source|
|
143
161
|
href = path_to_stylesheet(source, path_options)
|
144
|
-
|
162
|
+
if preload_links_header
|
163
|
+
preload_link = "<#{href}>; rel=preload; as=style"
|
164
|
+
preload_link += "; crossorigin=#{crossorigin}" unless crossorigin.nil?
|
165
|
+
preload_link += "; integrity=#{integrity}" unless integrity.nil?
|
166
|
+
preload_link += "; nopush" if nopush
|
167
|
+
preload_links << preload_link
|
168
|
+
end
|
145
169
|
tag_options = {
|
146
170
|
"rel" => "stylesheet",
|
147
171
|
"media" => "screen",
|
172
|
+
"crossorigin" => crossorigin,
|
148
173
|
"href" => href
|
149
174
|
}.merge!(options)
|
150
175
|
tag(:link, tag_options)
|
151
176
|
}.join("\n").html_safe
|
152
177
|
|
153
|
-
|
178
|
+
if preload_links_header
|
179
|
+
send_preload_links_header(preload_links)
|
180
|
+
end
|
154
181
|
|
155
182
|
sources_tags
|
156
183
|
end
|
@@ -241,6 +268,7 @@ module ActionView
|
|
241
268
|
# * <tt>:as</tt> - Override the auto-generated value for as attribute, calculated using +source+ extension and mime type.
|
242
269
|
# * <tt>:crossorigin</tt> - Specify the crossorigin attribute, required to load cross-origin resources.
|
243
270
|
# * <tt>:nopush</tt> - Specify if the use of server push is not desired for the resource. Defaults to +false+.
|
271
|
+
# * <tt>:integrity</tt> - Specify the integrity attribute.
|
244
272
|
#
|
245
273
|
# ==== Examples
|
246
274
|
#
|
@@ -266,12 +294,13 @@ module ActionView
|
|
266
294
|
# # => <link rel="preload" href="/media/audio.ogg" as="audio" type="audio/ogg" />
|
267
295
|
#
|
268
296
|
def preload_link_tag(source, options = {})
|
269
|
-
href =
|
297
|
+
href = path_to_asset(source, skip_pipeline: options.delete(:skip_pipeline))
|
270
298
|
extname = File.extname(source).downcase.delete(".")
|
271
|
-
mime_type = options.delete(:type) || Template::Types[extname]
|
299
|
+
mime_type = options.delete(:type) || Template::Types[extname]&.to_s
|
272
300
|
as_type = options.delete(:as) || resolve_link_as(extname, mime_type)
|
273
301
|
crossorigin = options.delete(:crossorigin)
|
274
302
|
crossorigin = "anonymous" if crossorigin == true || (crossorigin.blank? && as_type == "font")
|
303
|
+
integrity = options[:integrity]
|
275
304
|
nopush = options.delete(:nopush) || false
|
276
305
|
|
277
306
|
link_tag = tag.link(**{
|
@@ -282,12 +311,13 @@ module ActionView
|
|
282
311
|
crossorigin: crossorigin
|
283
312
|
}.merge!(options.symbolize_keys))
|
284
313
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
314
|
+
preload_link = "<#{href}>; rel=preload; as=#{as_type}"
|
315
|
+
preload_link += "; type=#{mime_type}" if mime_type
|
316
|
+
preload_link += "; crossorigin=#{crossorigin}" if crossorigin
|
317
|
+
preload_link += "; integrity=#{integrity}" if integrity
|
318
|
+
preload_link += "; nopush" if nopush
|
289
319
|
|
290
|
-
|
320
|
+
send_preload_links_header([preload_link])
|
291
321
|
|
292
322
|
link_tag
|
293
323
|
end
|
@@ -479,10 +509,20 @@ module ActionView
|
|
479
509
|
"style"
|
480
510
|
elsif extname == "vtt"
|
481
511
|
"track"
|
482
|
-
elsif (type = mime_type.to_s.split("/")[0]) && type.in?(%w(audio video font))
|
512
|
+
elsif (type = mime_type.to_s.split("/")[0]) && type.in?(%w(audio video font image))
|
483
513
|
type
|
484
514
|
end
|
485
515
|
end
|
516
|
+
|
517
|
+
def send_preload_links_header(preload_links)
|
518
|
+
if respond_to?(:request) && request
|
519
|
+
request.send_early_hints("Link" => preload_links.join("\n"))
|
520
|
+
end
|
521
|
+
|
522
|
+
if respond_to?(:response) && response
|
523
|
+
response.headers["Link"] = [response.headers["Link"].presence, *preload_links].compact.join(",")
|
524
|
+
end
|
525
|
+
end
|
486
526
|
end
|
487
527
|
end
|
488
528
|
end
|
@@ -52,7 +52,7 @@ module ActionView
|
|
52
52
|
# solution being slower. You should be sure to measure your actual
|
53
53
|
# performance across targeted browsers both before and after this change.
|
54
54
|
#
|
55
|
-
# To implement the corresponding hosts you can either
|
55
|
+
# To implement the corresponding hosts you can either set up four actual
|
56
56
|
# hosts or use wildcard DNS to CNAME the wildcard to a single asset host.
|
57
57
|
# You can read more about setting up your DNS CNAME records from your ISP.
|
58
58
|
#
|
@@ -80,7 +80,7 @@ module ActionView
|
|
80
80
|
# absolute path of the asset, for example "/assets/rails.png".
|
81
81
|
#
|
82
82
|
# ActionController::Base.asset_host = Proc.new { |source|
|
83
|
-
# if source.
|
83
|
+
# if source.end_with?('.css')
|
84
84
|
# "http://stylesheets.example.com"
|
85
85
|
# else
|
86
86
|
# "http://assets.example.com"
|
@@ -98,7 +98,7 @@ 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 with the command
|
101
|
+
# are precompiled with the command <tt>bin/rails assets:precompile</tt>. Make sure to use a
|
102
102
|
# +Proc+ instead of a lambda, since a +Proc+ allows missing parameters and sets them
|
103
103
|
# to +nil+.
|
104
104
|
#
|
@@ -133,6 +133,8 @@ module ActionView
|
|
133
133
|
# which is implemented by sprockets-rails.
|
134
134
|
#
|
135
135
|
# asset_path("application.js") # => "/assets/application-60aa4fdc5cea14baf5400fba1abf4f2a46a5166bad4772b1effe341570f07de9.js"
|
136
|
+
# asset_path('application.js', host: 'example.com') # => "//example.com/assets/application.js"
|
137
|
+
# asset_path("application.js", host: 'example.com', protocol: 'https') # => "https://example.com/assets/application.js"
|
136
138
|
#
|
137
139
|
# === Without the asset pipeline (<tt>skip_pipeline: true</tt>)
|
138
140
|
#
|
@@ -204,7 +206,7 @@ module ActionView
|
|
204
206
|
|
205
207
|
relative_url_root = defined?(config.relative_url_root) && config.relative_url_root
|
206
208
|
if relative_url_root
|
207
|
-
source = File.join(relative_url_root, source) unless source.
|
209
|
+
source = File.join(relative_url_root, source) unless source.start_with?("#{relative_url_root}/")
|
208
210
|
end
|
209
211
|
|
210
212
|
if host = compute_asset_host(source, options)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "set"
|
4
|
+
require "active_support/core_ext/symbol/starts_ends_with"
|
4
5
|
|
5
6
|
module ActionView
|
6
7
|
# = Action View Atom Feed Helpers
|
@@ -115,7 +116,7 @@ module ActionView
|
|
115
116
|
end
|
116
117
|
|
117
118
|
feed_opts = { "xml:lang" => options[:language] || "en-US", "xmlns" => "http://www.w3.org/2005/Atom" }
|
118
|
-
feed_opts.merge!(options).
|
119
|
+
feed_opts.merge!(options).select! { |k, _| k.start_with?("xml") }
|
119
120
|
|
120
121
|
xml.feed(feed_opts) do
|
121
122
|
xml.id(options[:id] || "tag:#{request.host},#{options[:schema_date]}:#{request.fullpath.split(".")[0]}")
|
@@ -24,8 +24,8 @@ module ActionView
|
|
24
24
|
# This approach will assume that when a new topic is added, you'll touch
|
25
25
|
# the project. The cache key generated from this call will be something like:
|
26
26
|
#
|
27
|
-
# views/template/action
|
28
|
-
# ^template path
|
27
|
+
# views/template/action:7a1156131a6928cb0026877f8b749ac9/projects/123
|
28
|
+
# ^template path ^template tree digest ^class ^id
|
29
29
|
#
|
30
30
|
# This cache key is stable, but it's combined with a cache version derived from the project
|
31
31
|
# record. When the project updated_at is touched, the #cache_version changes, even
|
@@ -165,7 +165,7 @@ module ActionView
|
|
165
165
|
# expire the cache.
|
166
166
|
def cache(name = {}, options = {}, &block)
|
167
167
|
if controller.respond_to?(:perform_caching) && controller.perform_caching
|
168
|
-
name_options = options.slice(:skip_digest
|
168
|
+
name_options = options.slice(:skip_digest)
|
169
169
|
safe_concat(fragment_for(cache_fragment_name(name, **name_options), options, &block))
|
170
170
|
else
|
171
171
|
yield
|
@@ -205,14 +205,11 @@ module ActionView
|
|
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
|
-
|
209
|
-
# The digest will be generated using +virtual_path:+ if it is provided.
|
210
|
-
#
|
211
|
-
def cache_fragment_name(name = {}, skip_digest: nil, virtual_path: nil, digest_path: nil)
|
208
|
+
def cache_fragment_name(name = {}, skip_digest: nil, digest_path: nil)
|
212
209
|
if skip_digest
|
213
210
|
name
|
214
211
|
else
|
215
|
-
fragment_name_with_digest(name,
|
212
|
+
fragment_name_with_digest(name, digest_path)
|
216
213
|
end
|
217
214
|
end
|
218
215
|
|
@@ -227,14 +224,11 @@ module ActionView
|
|
227
224
|
end
|
228
225
|
|
229
226
|
private
|
230
|
-
def fragment_name_with_digest(name,
|
231
|
-
|
232
|
-
|
233
|
-
if virtual_path || digest_path
|
234
|
-
name = controller.url_for(name).split("://").last if name.is_a?(Hash)
|
227
|
+
def fragment_name_with_digest(name, digest_path)
|
228
|
+
name = controller.url_for(name).split("://").last if name.is_a?(Hash)
|
235
229
|
|
230
|
+
if @current_template&.virtual_path || digest_path
|
236
231
|
digest_path ||= digest_path_from_template(@current_template)
|
237
|
-
|
238
232
|
[ digest_path, name ]
|
239
233
|
else
|
240
234
|
name
|
@@ -243,10 +237,10 @@ module ActionView
|
|
243
237
|
|
244
238
|
def fragment_for(name = {}, options = nil, &block)
|
245
239
|
if content = read_fragment_for(name, options)
|
246
|
-
@view_renderer.cache_hits[@virtual_path] = :hit if defined?(@view_renderer)
|
240
|
+
@view_renderer.cache_hits[@current_template&.virtual_path] = :hit if defined?(@view_renderer)
|
247
241
|
content
|
248
242
|
else
|
249
|
-
@view_renderer.cache_hits[@virtual_path] = :miss if defined?(@view_renderer)
|
243
|
+
@view_renderer.cache_hits[@current_template&.virtual_path] = :miss if defined?(@view_renderer)
|
250
244
|
write_fragment_for(name, options, &block)
|
251
245
|
end
|
252
246
|
end
|
@@ -197,8 +197,8 @@ module ActionView
|
|
197
197
|
# and +:name+ (string). A format string would be something like "%{name} (%<number>02d)" for example.
|
198
198
|
# See <tt>Kernel.sprintf</tt> for documentation on format sequences.
|
199
199
|
# * <tt>:date_separator</tt> - Specifies a string to separate the date fields. Default is "" (i.e. nothing).
|
200
|
-
# * <tt>:time_separator</tt> - Specifies a string to separate the time fields. Default is "
|
201
|
-
# * <tt>:datetime_separator</tt>- Specifies a string to separate the date and time fields. Default is "
|
200
|
+
# * <tt>:time_separator</tt> - Specifies a string to separate the time fields. Default is " : ".
|
201
|
+
# * <tt>:datetime_separator</tt>- Specifies a string to separate the date and time fields. Default is " — ".
|
202
202
|
# * <tt>:start_year</tt> - Set the start year for the year select. Default is <tt>Date.today.year - 5</tt> if
|
203
203
|
# you are creating new record. While editing existing record, <tt>:start_year</tt> defaults to
|
204
204
|
# the current selected year minus 5.
|
@@ -1053,7 +1053,7 @@ module ActionView
|
|
1053
1053
|
select_options[:class] = css_class_attribute(type, select_options[:class], @options[:with_css_classes]) if @options[:with_css_classes]
|
1054
1054
|
|
1055
1055
|
select_html = +"\n"
|
1056
|
-
select_html << content_tag("option", "", value: "") + "\n" if @options[:include_blank]
|
1056
|
+
select_html << content_tag("option", "", value: "", label: " ") + "\n" if @options[:include_blank]
|
1057
1057
|
select_html << prompt_option_tag(type, @options[:prompt]) + "\n" if @options[:prompt]
|
1058
1058
|
select_html << select_options_as_html
|
1059
1059
|
|
@@ -1101,7 +1101,8 @@ module ActionView
|
|
1101
1101
|
type: "hidden",
|
1102
1102
|
id: input_id_from_type(type),
|
1103
1103
|
name: input_name_from_type(type),
|
1104
|
-
value: value
|
1104
|
+
value: value,
|
1105
|
+
autocomplete: "off"
|
1105
1106
|
}.merge!(@html_options.slice(:disabled))
|
1106
1107
|
select_options[:disabled] = "disabled" if @options[:disabled]
|
1107
1108
|
|
@@ -1138,7 +1139,7 @@ module ActionView
|
|
1138
1139
|
first_visible = order.find { |type| !@options[:"discard_#{type}"] }
|
1139
1140
|
order.reverse_each do |type|
|
1140
1141
|
separator = separator(type) unless type == first_visible # don't add before first visible field
|
1141
|
-
select.insert(0, separator.to_s +
|
1142
|
+
select.insert(0, separator.to_s + public_send("select_#{type}").to_s)
|
1142
1143
|
end
|
1143
1144
|
select.html_safe
|
1144
1145
|
end
|