actionview 6.1.7.2 → 7.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +265 -261
- data/MIT-LICENSE +1 -0
- data/lib/action_view/base.rb +4 -7
- data/lib/action_view/buffers.rb +2 -2
- data/lib/action_view/cache_expiry.rb +46 -32
- 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 +6 -147
- data/lib/action_view/digestor.rb +7 -4
- data/lib/action_view/flows.rb +4 -4
- data/lib/action_view/gem_version.rb +5 -5
- data/lib/action_view/helpers/active_model_helper.rb +2 -2
- data/lib/action_view/helpers/asset_tag_helper.rb +95 -39
- data/lib/action_view/helpers/asset_url_helper.rb +16 -16
- data/lib/action_view/helpers/atom_feed_helper.rb +3 -4
- data/lib/action_view/helpers/cache_helper.rb +52 -3
- data/lib/action_view/helpers/capture_helper.rb +4 -4
- data/lib/action_view/helpers/controller_helper.rb +2 -2
- data/lib/action_view/helpers/csp_helper.rb +1 -1
- data/lib/action_view/helpers/csrf_helper.rb +2 -2
- data/lib/action_view/helpers/date_helper.rb +111 -43
- data/lib/action_view/helpers/debug_helper.rb +3 -1
- data/lib/action_view/helpers/form_helper.rb +211 -85
- data/lib/action_view/helpers/form_options_helper.rb +70 -33
- data/lib/action_view/helpers/form_tag_helper.rb +150 -53
- data/lib/action_view/helpers/javascript_helper.rb +3 -5
- data/lib/action_view/helpers/number_helper.rb +17 -16
- data/lib/action_view/helpers/output_safety_helper.rb +4 -4
- data/lib/action_view/helpers/rendering_helper.rb +5 -6
- data/lib/action_view/helpers/sanitize_helper.rb +3 -3
- data/lib/action_view/helpers/tag_helper.rb +37 -8
- data/lib/action_view/helpers/tags/base.rb +5 -25
- data/lib/action_view/helpers/tags/check_box.rb +1 -1
- data/lib/action_view/helpers/tags/collection_select.rb +1 -1
- data/lib/action_view/helpers/tags/file_field.rb +16 -0
- data/lib/action_view/helpers/tags/select.rb +1 -1
- data/lib/action_view/helpers/tags/time_field.rb +10 -1
- data/lib/action_view/helpers/tags/weekday_select.rb +28 -0
- data/lib/action_view/helpers/tags.rb +3 -2
- data/lib/action_view/helpers/text_helper.rb +25 -14
- data/lib/action_view/helpers/translation_helper.rb +12 -43
- data/lib/action_view/helpers/url_helper.rb +194 -123
- data/lib/action_view/helpers.rb +25 -25
- data/lib/action_view/layouts.rb +7 -4
- data/lib/action_view/lookup_context.rb +33 -52
- data/lib/action_view/model_naming.rb +2 -2
- data/lib/action_view/path_set.rb +16 -22
- data/lib/action_view/railtie.rb +19 -7
- data/lib/action_view/record_identifier.rb +1 -1
- data/lib/action_view/render_parser.rb +188 -0
- data/lib/action_view/renderer/abstract_renderer.rb +2 -2
- data/lib/action_view/renderer/partial_renderer.rb +1 -35
- data/lib/action_view/renderer/renderer.rb +4 -4
- data/lib/action_view/renderer/streaming_template_renderer.rb +3 -3
- data/lib/action_view/renderer/template_renderer.rb +6 -2
- data/lib/action_view/rendering.rb +3 -3
- data/lib/action_view/ripper_ast_parser.rb +198 -0
- data/lib/action_view/routing_url_for.rb +8 -5
- data/lib/action_view/template/error.rb +108 -13
- data/lib/action_view/template/handlers/erb.rb +6 -0
- data/lib/action_view/template/handlers.rb +3 -3
- data/lib/action_view/template/html.rb +3 -3
- data/lib/action_view/template/inline.rb +3 -3
- data/lib/action_view/template/raw_file.rb +3 -3
- data/lib/action_view/template/resolver.rb +89 -314
- data/lib/action_view/template/text.rb +3 -3
- data/lib/action_view/template/types.rb +14 -12
- data/lib/action_view/template.rb +18 -2
- 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 +7 -3
- data/lib/action_view/testing/resolvers.rb +11 -12
- data/lib/action_view/unbound_template.rb +33 -7
- data/lib/action_view/version.rb +1 -1
- data/lib/action_view/view_paths.rb +4 -4
- data/lib/action_view.rb +2 -3
- data/lib/assets/compiled/rails-ujs.js +36 -5
- metadata +23 -16
@@ -8,7 +8,7 @@ require "action_view/helpers/tag_helper"
|
|
8
8
|
|
9
9
|
module ActionView
|
10
10
|
# = Action View Asset Tag Helpers
|
11
|
-
module Helpers
|
11
|
+
module Helpers # :nodoc:
|
12
12
|
# This module provides methods for generating HTML that links views to assets such
|
13
13
|
# as images, JavaScripts, stylesheets, and feeds. These methods do not verify
|
14
14
|
# the assets exist before linking to them:
|
@@ -16,14 +16,15 @@ module ActionView
|
|
16
16
|
# image_tag("rails.png")
|
17
17
|
# # => <img src="/assets/rails.png" />
|
18
18
|
# stylesheet_link_tag("application")
|
19
|
-
# # => <link href="/assets/application.css?body=1"
|
19
|
+
# # => <link href="/assets/application.css?body=1" rel="stylesheet" />
|
20
20
|
module AssetTagHelper
|
21
|
-
extend ActiveSupport::Concern
|
22
|
-
|
23
21
|
include AssetUrlHelper
|
24
22
|
include TagHelper
|
25
23
|
|
24
|
+
mattr_accessor :image_loading
|
25
|
+
mattr_accessor :image_decoding
|
26
26
|
mattr_accessor :preload_links_header
|
27
|
+
mattr_accessor :apply_stylesheet_media_default
|
27
28
|
|
28
29
|
# Returns an HTML script tag for each of the +sources+ provided.
|
29
30
|
#
|
@@ -40,7 +41,7 @@ module ActionView
|
|
40
41
|
# When the Asset Pipeline is enabled, you can pass the name of your manifest as
|
41
42
|
# source, and include other JavaScript or CoffeeScript files inside the manifest.
|
42
43
|
#
|
43
|
-
# If the server supports Early Hints header links for these assets will be
|
44
|
+
# If the server supports Early Hints, header links for these assets will be
|
44
45
|
# automatically pushed.
|
45
46
|
#
|
46
47
|
# ==== Options
|
@@ -93,11 +94,12 @@ module ActionView
|
|
93
94
|
crossorigin = options.delete("crossorigin")
|
94
95
|
crossorigin = "anonymous" if crossorigin == true
|
95
96
|
integrity = options["integrity"]
|
97
|
+
rel = options["type"] == "module" ? "modulepreload" : "preload"
|
96
98
|
|
97
99
|
sources_tags = sources.uniq.map { |source|
|
98
100
|
href = path_to_javascript(source, path_options)
|
99
|
-
if preload_links_header && !options["defer"]
|
100
|
-
preload_link = "<#{href}>; rel
|
101
|
+
if preload_links_header && !options["defer"] && href.present? && !href.start_with?("data:")
|
102
|
+
preload_link = "<#{href}>; rel=#{rel}; as=script"
|
101
103
|
preload_link += "; crossorigin=#{crossorigin}" unless crossorigin.nil?
|
102
104
|
preload_link += "; integrity=#{integrity}" unless integrity.nil?
|
103
105
|
preload_link += "; nopush" if nopush
|
@@ -120,24 +122,41 @@ module ActionView
|
|
120
122
|
sources_tags
|
121
123
|
end
|
122
124
|
|
123
|
-
# Returns a stylesheet link tag for the sources specified as arguments.
|
124
|
-
#
|
125
|
+
# Returns a stylesheet link tag for the sources specified as arguments.
|
126
|
+
#
|
127
|
+
# When passing paths, the <tt>.css</tt> extension is optional.
|
128
|
+
# If you don't specify an extension, <tt>.css</tt> will be appended automatically.
|
129
|
+
# If you do not want <tt>.css</tt> appended to the path,
|
130
|
+
# set <tt>extname: false</tt> in the options.
|
125
131
|
# You can modify the link attributes by passing a hash as the last argument.
|
126
|
-
# For historical reasons, the 'media' attribute will always be present and defaults
|
127
|
-
# to "screen", so you must explicitly set it to "all" for the stylesheet(s) to
|
128
|
-
# apply to all media types.
|
129
132
|
#
|
130
|
-
# If the server supports Early Hints header links for these assets will be
|
133
|
+
# If the server supports Early Hints, header links for these assets will be
|
131
134
|
# automatically pushed.
|
132
135
|
#
|
136
|
+
# ==== Options
|
137
|
+
#
|
138
|
+
# * <tt>:extname</tt> - Append an extension to the generated URL unless the extension
|
139
|
+
# already exists. This only applies for relative URLs.
|
140
|
+
# * <tt>:protocol</tt> - Sets the protocol of the generated URL. This option only
|
141
|
+
# applies when a relative URL and +host+ options are provided.
|
142
|
+
# * <tt>:host</tt> - When a relative URL is provided the host is added to the
|
143
|
+
# that path.
|
144
|
+
# * <tt>:skip_pipeline</tt> - This option is used to bypass the asset pipeline
|
145
|
+
# when it is set to true.
|
146
|
+
#
|
147
|
+
# ==== Examples
|
148
|
+
#
|
133
149
|
# stylesheet_link_tag "style"
|
134
|
-
# # => <link href="/assets/style.css"
|
150
|
+
# # => <link href="/assets/style.css" rel="stylesheet" />
|
135
151
|
#
|
136
152
|
# stylesheet_link_tag "style.css"
|
137
|
-
# # => <link href="/assets/style.css"
|
153
|
+
# # => <link href="/assets/style.css" rel="stylesheet" />
|
138
154
|
#
|
139
155
|
# stylesheet_link_tag "http://www.example.com/style.css"
|
140
|
-
# # => <link href="http://www.example.com/style.css"
|
156
|
+
# # => <link href="http://www.example.com/style.css" rel="stylesheet" />
|
157
|
+
#
|
158
|
+
# stylesheet_link_tag "style.less", extname: false, skip_pipeline: true, rel: "stylesheet/less"
|
159
|
+
# # => <link href="/stylesheets/style.less" rel="stylesheet/less">
|
141
160
|
#
|
142
161
|
# stylesheet_link_tag "style", media: "all"
|
143
162
|
# # => <link href="/assets/style.css" media="all" rel="stylesheet" />
|
@@ -146,11 +165,11 @@ module ActionView
|
|
146
165
|
# # => <link href="/assets/style.css" media="print" rel="stylesheet" />
|
147
166
|
#
|
148
167
|
# stylesheet_link_tag "random.styles", "/css/stylish"
|
149
|
-
# # => <link href="/assets/random.styles"
|
150
|
-
# # <link href="/css/stylish.css"
|
168
|
+
# # => <link href="/assets/random.styles" rel="stylesheet" />
|
169
|
+
# # <link href="/css/stylish.css" rel="stylesheet" />
|
151
170
|
def stylesheet_link_tag(*sources)
|
152
171
|
options = sources.extract_options!.stringify_keys
|
153
|
-
path_options = options.extract!("protocol", "host", "skip_pipeline").symbolize_keys
|
172
|
+
path_options = options.extract!("protocol", "extname", "host", "skip_pipeline").symbolize_keys
|
154
173
|
preload_links = []
|
155
174
|
crossorigin = options.delete("crossorigin")
|
156
175
|
crossorigin = "anonymous" if crossorigin == true
|
@@ -159,7 +178,7 @@ module ActionView
|
|
159
178
|
|
160
179
|
sources_tags = sources.uniq.map { |source|
|
161
180
|
href = path_to_stylesheet(source, path_options)
|
162
|
-
if preload_links_header
|
181
|
+
if preload_links_header && href.present? && !href.start_with?("data:")
|
163
182
|
preload_link = "<#{href}>; rel=preload; as=style"
|
164
183
|
preload_link += "; crossorigin=#{crossorigin}" unless crossorigin.nil?
|
165
184
|
preload_link += "; integrity=#{integrity}" unless integrity.nil?
|
@@ -168,10 +187,14 @@ module ActionView
|
|
168
187
|
end
|
169
188
|
tag_options = {
|
170
189
|
"rel" => "stylesheet",
|
171
|
-
"media" => "screen",
|
172
190
|
"crossorigin" => crossorigin,
|
173
191
|
"href" => href
|
174
192
|
}.merge!(options)
|
193
|
+
|
194
|
+
if apply_stylesheet_media_default && tag_options["media"].blank?
|
195
|
+
tag_options["media"] = "screen"
|
196
|
+
end
|
197
|
+
|
175
198
|
tag(:link, tag_options)
|
176
199
|
}.join("\n").html_safe
|
177
200
|
|
@@ -235,14 +258,14 @@ module ActionView
|
|
235
258
|
#
|
236
259
|
# The helper gets the name of the favicon file as first argument, which
|
237
260
|
# defaults to "favicon.ico", and also supports +:rel+ and +:type+ options
|
238
|
-
# to override their defaults, "
|
261
|
+
# to override their defaults, "icon" and "image/x-icon"
|
239
262
|
# respectively:
|
240
263
|
#
|
241
264
|
# favicon_link_tag
|
242
|
-
# # => <link href="/assets/favicon.ico" rel="
|
265
|
+
# # => <link href="/assets/favicon.ico" rel="icon" type="image/x-icon" />
|
243
266
|
#
|
244
267
|
# favicon_link_tag 'myicon.ico'
|
245
|
-
# # => <link href="/assets/myicon.ico" rel="
|
268
|
+
# # => <link href="/assets/myicon.ico" rel="icon" type="image/x-icon" />
|
246
269
|
#
|
247
270
|
# Mobile Safari looks for a different link tag, pointing to an image that
|
248
271
|
# will be used if you add the page to the home screen of an iOS device.
|
@@ -252,7 +275,7 @@ module ActionView
|
|
252
275
|
# # => <link href="/assets/mb-icon.png" rel="apple-touch-icon" type="image/png" />
|
253
276
|
def favicon_link_tag(source = "favicon.ico", options = {})
|
254
277
|
tag("link", {
|
255
|
-
rel: "
|
278
|
+
rel: "icon",
|
256
279
|
type: "image/x-icon",
|
257
280
|
href: path_to_image(source, skip_pipeline: options.delete(:skip_pipeline))
|
258
281
|
}.merge!(options.symbolize_keys))
|
@@ -302,16 +325,17 @@ module ActionView
|
|
302
325
|
crossorigin = "anonymous" if crossorigin == true || (crossorigin.blank? && as_type == "font")
|
303
326
|
integrity = options[:integrity]
|
304
327
|
nopush = options.delete(:nopush) || false
|
328
|
+
rel = mime_type == "module" ? "modulepreload" : "preload"
|
305
329
|
|
306
330
|
link_tag = tag.link(**{
|
307
|
-
rel:
|
331
|
+
rel: rel,
|
308
332
|
href: href,
|
309
333
|
as: as_type,
|
310
334
|
type: mime_type,
|
311
335
|
crossorigin: crossorigin
|
312
336
|
}.merge!(options.symbolize_keys))
|
313
337
|
|
314
|
-
preload_link = "<#{href}>; rel
|
338
|
+
preload_link = "<#{href}>; rel=#{rel}; as=#{as_type}"
|
315
339
|
preload_link += "; type=#{mime_type}" if mime_type
|
316
340
|
preload_link += "; crossorigin=#{crossorigin}" if crossorigin
|
317
341
|
preload_link += "; integrity=#{integrity}" if integrity
|
@@ -382,6 +406,10 @@ module ActionView
|
|
382
406
|
end
|
383
407
|
|
384
408
|
options[:width], options[:height] = extract_dimensions(options.delete(:size)) if options[:size]
|
409
|
+
|
410
|
+
options[:loading] ||= image_loading if image_loading
|
411
|
+
options[:decoding] ||= image_decoding if image_decoding
|
412
|
+
|
385
413
|
tag("img", options)
|
386
414
|
end
|
387
415
|
|
@@ -489,9 +517,9 @@ module ActionView
|
|
489
517
|
|
490
518
|
def extract_dimensions(size)
|
491
519
|
size = size.to_s
|
492
|
-
if /\A\d+x\d
|
520
|
+
if /\A(\d+|\d+.\d+)x(\d+|\d+.\d+)\z/.match?(size)
|
493
521
|
size.split("x")
|
494
|
-
elsif /\A\d
|
522
|
+
elsif /\A(\d+|\d+.\d+)\z/.match?(size)
|
495
523
|
[size, size]
|
496
524
|
end
|
497
525
|
end
|
@@ -503,24 +531,52 @@ module ActionView
|
|
503
531
|
end
|
504
532
|
|
505
533
|
def resolve_link_as(extname, mime_type)
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
"
|
512
|
-
elsif (type = mime_type.to_s.split("/")[0]) && type.in?(%w(audio video font image))
|
513
|
-
type
|
534
|
+
case extname
|
535
|
+
when "js" then "script"
|
536
|
+
when "css" then "style"
|
537
|
+
when "vtt" then "track"
|
538
|
+
else
|
539
|
+
mime_type.to_s.split("/").first.presence_in(%w(audio video font image))
|
514
540
|
end
|
515
541
|
end
|
516
542
|
|
517
|
-
|
543
|
+
MAX_HEADER_SIZE = 8_000 # Some HTTP client and proxies have a 8kiB header limit
|
544
|
+
def send_preload_links_header(preload_links, max_header_size: MAX_HEADER_SIZE)
|
545
|
+
return if preload_links.empty?
|
546
|
+
return if respond_to?(:response) && response&.sending?
|
547
|
+
|
518
548
|
if respond_to?(:request) && request
|
519
549
|
request.send_early_hints("Link" => preload_links.join("\n"))
|
520
550
|
end
|
521
551
|
|
522
552
|
if respond_to?(:response) && response
|
523
|
-
|
553
|
+
header = response.headers["Link"]
|
554
|
+
header = header ? header.dup : +""
|
555
|
+
|
556
|
+
# rindex count characters not bytes, but we assume non-ascii characters
|
557
|
+
# are rare in urls, and we have a 192 bytes margin.
|
558
|
+
last_line_offset = header.rindex("\n")
|
559
|
+
last_line_size = if last_line_offset
|
560
|
+
header.bytesize - last_line_offset
|
561
|
+
else
|
562
|
+
header.bytesize
|
563
|
+
end
|
564
|
+
|
565
|
+
preload_links.each do |link|
|
566
|
+
if link.bytesize + last_line_size + 1 < max_header_size
|
567
|
+
unless header.empty?
|
568
|
+
header << ","
|
569
|
+
last_line_size += 1
|
570
|
+
end
|
571
|
+
else
|
572
|
+
header << "\n"
|
573
|
+
last_line_size = 0
|
574
|
+
end
|
575
|
+
header << link
|
576
|
+
last_line_size += link.bytesize
|
577
|
+
end
|
578
|
+
|
579
|
+
response.headers["Link"] = header
|
524
580
|
end
|
525
581
|
end
|
526
582
|
end
|
@@ -4,7 +4,7 @@ require "zlib"
|
|
4
4
|
|
5
5
|
module ActionView
|
6
6
|
# = Action View Asset URL Helpers
|
7
|
-
module Helpers
|
7
|
+
module Helpers # :nodoc:
|
8
8
|
# This module provides methods for generating asset paths and
|
9
9
|
# URLs.
|
10
10
|
#
|
@@ -31,7 +31,7 @@ module ActionView
|
|
31
31
|
# image_tag("rails.png")
|
32
32
|
# # => <img src="http://assets.example.com/assets/rails.png" />
|
33
33
|
# stylesheet_link_tag("application")
|
34
|
-
# # => <link href="http://assets.example.com/assets/application.css"
|
34
|
+
# # => <link href="http://assets.example.com/assets/application.css" rel="stylesheet" />
|
35
35
|
#
|
36
36
|
# Browsers open a limited number of simultaneous connections to a single
|
37
37
|
# host. The exact number varies by browser and version. This limit may cause
|
@@ -44,7 +44,7 @@ module ActionView
|
|
44
44
|
# image_tag("rails.png")
|
45
45
|
# # => <img src="http://assets0.example.com/assets/rails.png" />
|
46
46
|
# stylesheet_link_tag("application")
|
47
|
-
# # => <link href="http://assets2.example.com/assets/application.css"
|
47
|
+
# # => <link href="http://assets2.example.com/assets/application.css" rel="stylesheet" />
|
48
48
|
#
|
49
49
|
# This may improve the asset loading performance of your application.
|
50
50
|
# It is also possible the combination of additional connection overhead
|
@@ -65,12 +65,12 @@ module ActionView
|
|
65
65
|
# +asset_host+ to a proc like this:
|
66
66
|
#
|
67
67
|
# ActionController::Base.asset_host = Proc.new { |source|
|
68
|
-
# "http://assets#{Digest::
|
68
|
+
# "http://assets#{OpenSSL::Digest::SHA256.hexdigest(source).to_i(16) % 2 + 1}.example.com"
|
69
69
|
# }
|
70
70
|
# image_tag("rails.png")
|
71
71
|
# # => <img src="http://assets1.example.com/assets/rails.png" />
|
72
72
|
# stylesheet_link_tag("application")
|
73
|
-
# # => <link href="http://assets2.example.com/assets/application.css"
|
73
|
+
# # => <link href="http://assets2.example.com/assets/application.css" rel="stylesheet" />
|
74
74
|
#
|
75
75
|
# The example above generates "http://assets1.example.com" and
|
76
76
|
# "http://assets2.example.com". This option is useful for example if
|
@@ -89,7 +89,7 @@ module ActionView
|
|
89
89
|
# image_tag("rails.png")
|
90
90
|
# # => <img src="http://assets.example.com/assets/rails.png" />
|
91
91
|
# stylesheet_link_tag("application")
|
92
|
-
# # => <link href="http://stylesheets.example.com/assets/application.css"
|
92
|
+
# # => <link href="http://stylesheets.example.com/assets/application.css" rel="stylesheet" />
|
93
93
|
#
|
94
94
|
# Alternatively you may ask for a second parameter +request+. That one is
|
95
95
|
# particularly useful for serving assets from an SSL-protected page. The
|
@@ -121,7 +121,7 @@ module ActionView
|
|
121
121
|
URI_REGEXP = %r{^[-a-z]+://|^(?:cid|data):|^//}i
|
122
122
|
|
123
123
|
# This is the entry point for all assets.
|
124
|
-
# When using
|
124
|
+
# When using an asset pipeline gem (e.g. propshaft or sprockets-rails), the
|
125
125
|
# behavior is "enhanced". You can bypass the asset pipeline by passing in
|
126
126
|
# <tt>skip_pipeline: true</tt> to the options.
|
127
127
|
#
|
@@ -130,7 +130,7 @@ module ActionView
|
|
130
130
|
# === With the asset pipeline
|
131
131
|
#
|
132
132
|
# All options passed to +asset_path+ will be passed to +compute_asset_path+
|
133
|
-
# which is implemented by
|
133
|
+
# which is implemented by asset pipeline gems.
|
134
134
|
#
|
135
135
|
# asset_path("application.js") # => "/assets/application-60aa4fdc5cea14baf5400fba1abf4f2a46a5166bad4772b1effe341570f07de9.js"
|
136
136
|
# asset_path('application.js', host: 'example.com') # => "//example.com/assets/application.js"
|
@@ -190,7 +190,7 @@ module ActionView
|
|
190
190
|
return "" if source.blank?
|
191
191
|
return source if URI_REGEXP.match?(source)
|
192
192
|
|
193
|
-
tail, source = source[/([
|
193
|
+
tail, source = source[/([?#].+)$/], source.sub(/([?#].+)$/, "")
|
194
194
|
|
195
195
|
if extname = compute_asset_extname(source, options)
|
196
196
|
source = "#{source}#{extname}"
|
@@ -219,7 +219,7 @@ module ActionView
|
|
219
219
|
|
220
220
|
# Computes the full URL to an asset in the public directory. This
|
221
221
|
# will use +asset_path+ internally, so most of their behaviors
|
222
|
-
# will be the same. If
|
222
|
+
# will be the same. If +:host+ options is set, it overwrites global
|
223
223
|
# +config.action_controller.asset_host+ setting.
|
224
224
|
#
|
225
225
|
# All other options provided are forwarded to +asset_path+ call.
|
@@ -324,7 +324,7 @@ module ActionView
|
|
324
324
|
|
325
325
|
# Computes the full URL to a JavaScript asset in the public javascripts directory.
|
326
326
|
# This will use +javascript_path+ internally, so most of their behaviors will be the same.
|
327
|
-
# Since +javascript_url+ is based on +asset_url+ method you can set
|
327
|
+
# Since +javascript_url+ is based on +asset_url+ method you can set +:host+ options. If +:host+
|
328
328
|
# options is set, it overwrites global +config.action_controller.asset_host+ setting.
|
329
329
|
#
|
330
330
|
# javascript_url "js/xmlhr.js", host: "http://stage.example.com" # => http://stage.example.com/assets/js/xmlhr.js
|
@@ -351,7 +351,7 @@ module ActionView
|
|
351
351
|
|
352
352
|
# Computes the full URL to a stylesheet asset in the public stylesheets directory.
|
353
353
|
# This will use +stylesheet_path+ internally, so most of their behaviors will be the same.
|
354
|
-
# Since +stylesheet_url+ is based on +asset_url+ method you can set
|
354
|
+
# Since +stylesheet_url+ is based on +asset_url+ method you can set +:host+ options. If +:host+
|
355
355
|
# options is set, it overwrites global +config.action_controller.asset_host+ setting.
|
356
356
|
#
|
357
357
|
# stylesheet_url "css/style.css", host: "http://stage.example.com" # => http://stage.example.com/assets/css/style.css
|
@@ -381,7 +381,7 @@ module ActionView
|
|
381
381
|
|
382
382
|
# Computes the full URL to an image asset.
|
383
383
|
# This will use +image_path+ internally, so most of their behaviors will be the same.
|
384
|
-
# Since +image_url+ is based on +asset_url+ method you can set
|
384
|
+
# Since +image_url+ is based on +asset_url+ method you can set +:host+ options. If +:host+
|
385
385
|
# options is set, it overwrites global +config.action_controller.asset_host+ setting.
|
386
386
|
#
|
387
387
|
# image_url "edit.png", host: "http://stage.example.com" # => http://stage.example.com/assets/edit.png
|
@@ -407,7 +407,7 @@ module ActionView
|
|
407
407
|
|
408
408
|
# Computes the full URL to a video asset in the public videos directory.
|
409
409
|
# This will use +video_path+ internally, so most of their behaviors will be the same.
|
410
|
-
# Since +video_url+ is based on +asset_url+ method you can set
|
410
|
+
# Since +video_url+ is based on +asset_url+ method you can set +:host+ options. If +:host+
|
411
411
|
# options is set, it overwrites global +config.action_controller.asset_host+ setting.
|
412
412
|
#
|
413
413
|
# video_url "hd.avi", host: "http://stage.example.com" # => http://stage.example.com/videos/hd.avi
|
@@ -433,7 +433,7 @@ module ActionView
|
|
433
433
|
|
434
434
|
# Computes the full URL to an audio asset in the public audios directory.
|
435
435
|
# This will use +audio_path+ internally, so most of their behaviors will be the same.
|
436
|
-
# Since +audio_url+ is based on +asset_url+ method you can set
|
436
|
+
# Since +audio_url+ is based on +asset_url+ method you can set +:host+ options. If +:host+
|
437
437
|
# options is set, it overwrites global +config.action_controller.asset_host+ setting.
|
438
438
|
#
|
439
439
|
# audio_url "horse.wav", host: "http://stage.example.com" # => http://stage.example.com/audios/horse.wav
|
@@ -458,7 +458,7 @@ module ActionView
|
|
458
458
|
|
459
459
|
# Computes the full URL to a font asset.
|
460
460
|
# This will use +font_path+ internally, so most of their behaviors will be the same.
|
461
|
-
# Since +font_url+ is based on +asset_url+ method you can set
|
461
|
+
# Since +font_url+ is based on +asset_url+ method you can set +:host+ options. If +:host+
|
462
462
|
# options is set, it overwrites global +config.action_controller.asset_host+ setting.
|
463
463
|
#
|
464
464
|
# font_url "font.ttf", host: "http://stage.example.com" # => http://stage.example.com/fonts/font.ttf
|
@@ -1,11 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "set"
|
4
|
-
require "active_support/core_ext/symbol/starts_ends_with"
|
5
4
|
|
6
5
|
module ActionView
|
7
6
|
# = Action View Atom Feed Helpers
|
8
|
-
module Helpers
|
7
|
+
module Helpers # :nodoc:
|
9
8
|
module AtomFeedHelper
|
10
9
|
# Adds easy defaults to writing Atom feeds with the Builder template engine (this does not work on ERB or any other
|
11
10
|
# template languages).
|
@@ -127,7 +126,7 @@ module ActionView
|
|
127
126
|
end
|
128
127
|
end
|
129
128
|
|
130
|
-
class AtomBuilder
|
129
|
+
class AtomBuilder # :nodoc:
|
131
130
|
XHTML_TAG_NAMES = %w(content rights title subtitle summary).to_set
|
132
131
|
|
133
132
|
def initialize(xml)
|
@@ -161,7 +160,7 @@ module ActionView
|
|
161
160
|
end
|
162
161
|
end
|
163
162
|
|
164
|
-
class AtomFeedBuilder < AtomBuilder
|
163
|
+
class AtomFeedBuilder < AtomBuilder # :nodoc:
|
165
164
|
def initialize(xml, view, feed_options = {})
|
166
165
|
@xml, @view, @feed_options = xml, view, feed_options
|
167
166
|
end
|
@@ -2,8 +2,10 @@
|
|
2
2
|
|
3
3
|
module ActionView
|
4
4
|
# = Action View Cache Helper
|
5
|
-
module Helpers
|
5
|
+
module Helpers # :nodoc:
|
6
6
|
module CacheHelper
|
7
|
+
class UncacheableFragmentError < StandardError; end
|
8
|
+
|
7
9
|
# This helper exposes a method for caching fragments of a view
|
8
10
|
# rather than an entire action or page. This technique is useful
|
9
11
|
# caching pieces like menus, lists of new topics, static HTML
|
@@ -165,8 +167,10 @@ module ActionView
|
|
165
167
|
# expire the cache.
|
166
168
|
def cache(name = {}, options = {}, &block)
|
167
169
|
if controller.respond_to?(:perform_caching) && controller.perform_caching
|
168
|
-
|
169
|
-
|
170
|
+
CachingRegistry.track_caching do
|
171
|
+
name_options = options.slice(:skip_digest)
|
172
|
+
safe_concat(fragment_for(cache_fragment_name(name, **name_options), options, &block))
|
173
|
+
end
|
170
174
|
else
|
171
175
|
yield
|
172
176
|
end
|
@@ -174,6 +178,34 @@ module ActionView
|
|
174
178
|
nil
|
175
179
|
end
|
176
180
|
|
181
|
+
# Returns whether the current view fragment is within a +cache+ block.
|
182
|
+
#
|
183
|
+
# Useful when certain fragments aren't cacheable:
|
184
|
+
#
|
185
|
+
# <% cache project do %>
|
186
|
+
# <% raise StandardError, "Caching private data!" if caching? %>
|
187
|
+
# <% end %>
|
188
|
+
def caching?
|
189
|
+
CachingRegistry.caching?
|
190
|
+
end
|
191
|
+
|
192
|
+
# Raises +UncacheableFragmentError+ when called from within a +cache+ block.
|
193
|
+
#
|
194
|
+
# Useful to denote helper methods that can't participate in fragment caching:
|
195
|
+
#
|
196
|
+
# def project_name_with_time(project)
|
197
|
+
# uncacheable!
|
198
|
+
# "#{project.name} - #{Time.now}"
|
199
|
+
# end
|
200
|
+
#
|
201
|
+
# # Which will then raise if used within a +cache+ block:
|
202
|
+
# <% cache project do %>
|
203
|
+
# <%= project_name_with_time(project) %>
|
204
|
+
# <% end %>
|
205
|
+
def uncacheable!
|
206
|
+
raise UncacheableFragmentError, "can't be fragment cached" if caching?
|
207
|
+
end
|
208
|
+
|
177
209
|
# Cache fragments of a view if +condition+ is true
|
178
210
|
#
|
179
211
|
# <% cache_if admin?, project do %>
|
@@ -259,6 +291,23 @@ module ActionView
|
|
259
291
|
end
|
260
292
|
controller.write_fragment(name, fragment, options)
|
261
293
|
end
|
294
|
+
|
295
|
+
module CachingRegistry # :nodoc:
|
296
|
+
extend self
|
297
|
+
|
298
|
+
def caching?
|
299
|
+
ActiveSupport::IsolatedExecutionState[:action_view_caching] ||= false
|
300
|
+
end
|
301
|
+
|
302
|
+
def track_caching
|
303
|
+
caching_was = ActiveSupport::IsolatedExecutionState[:action_view_caching]
|
304
|
+
ActiveSupport::IsolatedExecutionState[:action_view_caching] = true
|
305
|
+
|
306
|
+
yield
|
307
|
+
ensure
|
308
|
+
ActiveSupport::IsolatedExecutionState[:action_view_caching] = caching_was
|
309
|
+
end
|
310
|
+
end
|
262
311
|
end
|
263
312
|
end
|
264
313
|
end
|
@@ -4,7 +4,7 @@ require "active_support/core_ext/string/output_safety"
|
|
4
4
|
|
5
5
|
module ActionView
|
6
6
|
# = Action View Capture Helper
|
7
|
-
module Helpers
|
7
|
+
module Helpers # :nodoc:
|
8
8
|
# CaptureHelper exposes methods to let you extract generated markup which
|
9
9
|
# can be used in other parts of a template or layout file.
|
10
10
|
#
|
@@ -121,7 +121,7 @@ module ActionView
|
|
121
121
|
# <li><%= link_to 'Home', action: 'index' %></li>
|
122
122
|
# <% end %>
|
123
123
|
#
|
124
|
-
#
|
124
|
+
# And in another place:
|
125
125
|
#
|
126
126
|
# <% content_for :navigation do %>
|
127
127
|
# <li><%= link_to 'Login', action: 'login' %></li>
|
@@ -137,7 +137,7 @@ module ActionView
|
|
137
137
|
# <li><%= link_to 'Home', action: 'index' %></li>
|
138
138
|
# <% end %>
|
139
139
|
#
|
140
|
-
# <%#
|
140
|
+
# <%# Add some other content, or use a different template: %>
|
141
141
|
#
|
142
142
|
# <% content_for :navigation, flush: true do %>
|
143
143
|
# <li><%= link_to 'Login', action: 'login' %></li>
|
@@ -198,7 +198,7 @@ module ActionView
|
|
198
198
|
|
199
199
|
# Use an alternate output buffer for the duration of the block.
|
200
200
|
# Defaults to a new empty string.
|
201
|
-
def with_output_buffer(buf = nil)
|
201
|
+
def with_output_buffer(buf = nil) # :nodoc:
|
202
202
|
unless buf
|
203
203
|
buf = ActionView::OutputBuffer.new
|
204
204
|
if output_buffer && output_buffer.respond_to?(:encoding)
|
@@ -3,10 +3,10 @@
|
|
3
3
|
require "active_support/core_ext/module/attr_internal"
|
4
4
|
|
5
5
|
module ActionView
|
6
|
-
module Helpers
|
6
|
+
module Helpers # :nodoc:
|
7
7
|
# This module keeps all methods and behavior in ActionView
|
8
8
|
# that simply delegates to the controller.
|
9
|
-
module ControllerHelper
|
9
|
+
module ControllerHelper # :nodoc:
|
10
10
|
attr_internal :controller, :request
|
11
11
|
|
12
12
|
CONTROLLER_DELEGATES = [:request_forgery_protection_token, :params,
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module ActionView
|
4
4
|
# = Action View CSRF Helper
|
5
|
-
module Helpers
|
5
|
+
module Helpers # :nodoc:
|
6
6
|
module CsrfHelper
|
7
7
|
# Returns meta tags "csrf-param" and "csrf-token" with the name of the cross-site
|
8
8
|
# request forgery protection parameter and token, respectively.
|
@@ -17,7 +17,7 @@ module ActionView
|
|
17
17
|
# You don't need to use these tags for regular forms as they generate their own hidden fields.
|
18
18
|
#
|
19
19
|
# For AJAX requests other than GETs, extract the "csrf-token" from the meta-tag and send as the
|
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
23
|
if defined?(protect_against_forgery?) && protect_against_forgery?
|