actionview 6.1.7.2 → 7.0.5
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 +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?
|