actionview 7.1.6 → 7.2.3
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 +99 -425
- data/README.rdoc +1 -1
- data/lib/action_view/base.rb +24 -9
- data/lib/action_view/cache_expiry.rb +9 -3
- data/lib/action_view/dependency_tracker/{ripper_tracker.rb → ruby_tracker.rb} +4 -3
- data/lib/action_view/dependency_tracker.rb +1 -1
- data/lib/action_view/digestor.rb +6 -2
- data/lib/action_view/gem_version.rb +2 -2
- data/lib/action_view/helpers/asset_tag_helper.rb +19 -7
- data/lib/action_view/helpers/atom_feed_helper.rb +1 -1
- data/lib/action_view/helpers/cache_helper.rb +2 -2
- data/lib/action_view/helpers/csrf_helper.rb +1 -1
- data/lib/action_view/helpers/form_helper.rb +222 -217
- data/lib/action_view/helpers/form_options_helper.rb +6 -3
- data/lib/action_view/helpers/form_tag_helper.rb +80 -47
- data/lib/action_view/helpers/output_safety_helper.rb +5 -6
- data/lib/action_view/helpers/tag_helper.rb +208 -18
- data/lib/action_view/helpers/tags/collection_helpers.rb +2 -1
- data/lib/action_view/helpers/text_helper.rb +11 -4
- data/lib/action_view/helpers/url_helper.rb +3 -77
- data/lib/action_view/layouts.rb +8 -10
- data/lib/action_view/log_subscriber.rb +8 -4
- data/lib/action_view/railtie.rb +0 -1
- data/lib/action_view/render_parser/prism_render_parser.rb +127 -0
- data/lib/action_view/{ripper_ast_parser.rb → render_parser/ripper_render_parser.rb} +152 -9
- data/lib/action_view/render_parser.rb +21 -169
- data/lib/action_view/renderer/abstract_renderer.rb +1 -1
- data/lib/action_view/renderer/partial_renderer.rb +2 -2
- data/lib/action_view/renderer/renderer.rb +32 -38
- data/lib/action_view/renderer/template_renderer.rb +3 -3
- data/lib/action_view/rendering.rb +4 -4
- data/lib/action_view/template/error.rb +11 -0
- data/lib/action_view/template/handlers/erb.rb +45 -37
- data/lib/action_view/template/renderable.rb +7 -1
- data/lib/action_view/template/resolver.rb +0 -2
- data/lib/action_view/template.rb +36 -8
- data/lib/action_view/test_case.rb +7 -10
- data/lib/action_view.rb +1 -0
- metadata +14 -13
data/lib/action_view/base.rb
CHANGED
|
@@ -80,6 +80,23 @@ module ActionView # :nodoc:
|
|
|
80
80
|
# This is useful in cases where you aren't sure if the local variable has been assigned. Alternatively, you could also use
|
|
81
81
|
# <tt>defined? headline</tt> to first check if the variable has been assigned before using it.
|
|
82
82
|
#
|
|
83
|
+
# By default, templates will accept any <tt>locals</tt> as keyword arguments. To restrict what <tt>locals</tt> a template accepts, add a <tt>locals:</tt> magic comment:
|
|
84
|
+
#
|
|
85
|
+
# <%# locals: (headline:) %>
|
|
86
|
+
#
|
|
87
|
+
# Headline: <%= headline %>
|
|
88
|
+
#
|
|
89
|
+
# In cases where the local variables are optional, declare the keyword argument with a default value:
|
|
90
|
+
#
|
|
91
|
+
# <%# locals: (headline: nil) %>
|
|
92
|
+
#
|
|
93
|
+
# <% unless headline.nil? %>
|
|
94
|
+
# Headline: <%= headline %>
|
|
95
|
+
# <% end %>
|
|
96
|
+
#
|
|
97
|
+
# Read more about strict locals in {Action View Overview}[https://guides.rubyonrails.org/action_view_overview.html#strict-locals]
|
|
98
|
+
# in the guides.
|
|
99
|
+
#
|
|
83
100
|
# === Template caching
|
|
84
101
|
#
|
|
85
102
|
# By default, \Rails will compile each template to a method in order to render it. When you alter a template,
|
|
@@ -248,16 +265,14 @@ module ActionView # :nodoc:
|
|
|
248
265
|
|
|
249
266
|
if has_strict_locals
|
|
250
267
|
begin
|
|
251
|
-
public_send(method, buffer, **locals, &block)
|
|
268
|
+
public_send(method, locals, buffer, **locals, &block)
|
|
252
269
|
rescue ArgumentError => argument_error
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
gsub("no keywords accepted", "no locals accepted")
|
|
260
|
-
)
|
|
270
|
+
public_send_line = __LINE__ - 2
|
|
271
|
+
frame = argument_error.backtrace_locations[1]
|
|
272
|
+
if frame.path == __FILE__ && frame.lineno == public_send_line
|
|
273
|
+
raise StrictLocalsError.new(argument_error, @current_template)
|
|
274
|
+
end
|
|
275
|
+
raise
|
|
261
276
|
end
|
|
262
277
|
else
|
|
263
278
|
public_send(method, locals, buffer, &block)
|
|
@@ -10,16 +10,17 @@ module ActionView
|
|
|
10
10
|
@watcher = nil
|
|
11
11
|
@previous_change = false
|
|
12
12
|
|
|
13
|
-
rebuild_watcher
|
|
14
|
-
|
|
15
13
|
ActionView::PathRegistry.file_system_resolver_hooks << method(:rebuild_watcher)
|
|
16
14
|
end
|
|
17
15
|
|
|
18
16
|
def updated?
|
|
17
|
+
build_watcher unless @watcher
|
|
19
18
|
@previous_change || @watcher.updated?
|
|
20
19
|
end
|
|
21
20
|
|
|
22
21
|
def execute
|
|
22
|
+
return unless @watcher
|
|
23
|
+
|
|
23
24
|
watcher = nil
|
|
24
25
|
@mutex.synchronize do
|
|
25
26
|
@previous_change = false
|
|
@@ -33,7 +34,7 @@ module ActionView
|
|
|
33
34
|
ActionView::LookupContext::DetailsKey.clear
|
|
34
35
|
end
|
|
35
36
|
|
|
36
|
-
def
|
|
37
|
+
def build_watcher
|
|
37
38
|
@mutex.synchronize do
|
|
38
39
|
old_watcher = @watcher
|
|
39
40
|
|
|
@@ -51,6 +52,11 @@ module ActionView
|
|
|
51
52
|
end
|
|
52
53
|
end
|
|
53
54
|
|
|
55
|
+
def rebuild_watcher
|
|
56
|
+
return unless @watcher
|
|
57
|
+
build_watcher
|
|
58
|
+
end
|
|
59
|
+
|
|
54
60
|
def dirs_to_watch
|
|
55
61
|
all_view_paths.uniq.sort
|
|
56
62
|
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module ActionView
|
|
4
4
|
class DependencyTracker # :nodoc:
|
|
5
|
-
class
|
|
5
|
+
class RubyTracker # :nodoc:
|
|
6
6
|
EXPLICIT_DEPENDENCY = /# Template Dependency: (\S+)/
|
|
7
7
|
|
|
8
8
|
def self.call(name, template, view_paths = nil)
|
|
@@ -17,8 +17,9 @@ module ActionView
|
|
|
17
17
|
true
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def initialize(name, template, view_paths = nil)
|
|
20
|
+
def initialize(name, template, view_paths = nil, parser_class: RenderParser::Default)
|
|
21
21
|
@name, @template, @view_paths = name, template, view_paths
|
|
22
|
+
@parser_class = parser_class
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
private
|
|
@@ -29,7 +30,7 @@ module ActionView
|
|
|
29
30
|
|
|
30
31
|
compiled_source = template.handler.call(template, template.source)
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
@parser_class.new(@name, compiled_source).render_calls.filter_map do |render_call|
|
|
33
34
|
next if render_call.end_with?("/_")
|
|
34
35
|
render_call.gsub(%r|/_|, "/")
|
|
35
36
|
end
|
data/lib/action_view/digestor.rb
CHANGED
|
@@ -107,8 +107,12 @@ module ActionView
|
|
|
107
107
|
end.join("-")
|
|
108
108
|
end
|
|
109
109
|
|
|
110
|
-
def to_dep_map
|
|
111
|
-
|
|
110
|
+
def to_dep_map(seen = Set.new.compare_by_identity)
|
|
111
|
+
if seen.add?(self)
|
|
112
|
+
children.any? ? { name => children.map { |c| c.to_dep_map(seen) } } : name
|
|
113
|
+
else # the tree has a cycle
|
|
114
|
+
name
|
|
115
|
+
end
|
|
112
116
|
end
|
|
113
117
|
end
|
|
114
118
|
|
|
@@ -68,6 +68,8 @@ module ActionView
|
|
|
68
68
|
# attribute, which indicates to the browser that the script is meant to
|
|
69
69
|
# be executed after the document has been parsed. Additionally, prevents
|
|
70
70
|
# sending the Preload Links header.
|
|
71
|
+
# * <tt>:nopush</tt> - Specify if the use of server push is not desired
|
|
72
|
+
# for the script. Defaults to +true+.
|
|
71
73
|
#
|
|
72
74
|
# Any other specified options will be treated as HTML attributes for the
|
|
73
75
|
# +script+ tag.
|
|
@@ -113,11 +115,11 @@ module ActionView
|
|
|
113
115
|
path_options = options.extract!("protocol", "extname", "host", "skip_pipeline").symbolize_keys
|
|
114
116
|
preload_links = []
|
|
115
117
|
use_preload_links_header = options["preload_links_header"].nil? ? preload_links_header : options.delete("preload_links_header")
|
|
116
|
-
nopush = options["nopush"].nil?
|
|
118
|
+
nopush = options["nopush"].nil? || options.delete("nopush")
|
|
117
119
|
crossorigin = options.delete("crossorigin")
|
|
118
120
|
crossorigin = "anonymous" if crossorigin == true
|
|
119
121
|
integrity = options["integrity"]
|
|
120
|
-
rel = options["type"] == "module" ? "modulepreload" : "preload"
|
|
122
|
+
rel = options["type"] == "module" || options["type"] == :module ? "modulepreload" : "preload"
|
|
121
123
|
|
|
122
124
|
sources_tags = sources.uniq.map { |source|
|
|
123
125
|
href = path_to_javascript(source, path_options)
|
|
@@ -166,6 +168,10 @@ module ActionView
|
|
|
166
168
|
# that path.
|
|
167
169
|
# * <tt>:skip_pipeline</tt> - This option is used to bypass the asset pipeline
|
|
168
170
|
# when it is set to true.
|
|
171
|
+
# * <tt>:nonce</tt> - When set to true, adds an automatic nonce value if
|
|
172
|
+
# you have Content Security Policy enabled.
|
|
173
|
+
# * <tt>:nopush</tt> - Specify if the use of server push is not desired
|
|
174
|
+
# for the stylesheet. Defaults to +true+.
|
|
169
175
|
#
|
|
170
176
|
# ==== Examples
|
|
171
177
|
#
|
|
@@ -190,6 +196,9 @@ module ActionView
|
|
|
190
196
|
# stylesheet_link_tag "random.styles", "/css/stylish"
|
|
191
197
|
# # => <link href="/assets/random.styles" rel="stylesheet" />
|
|
192
198
|
# # <link href="/css/stylish.css" rel="stylesheet" />
|
|
199
|
+
#
|
|
200
|
+
# stylesheet_link_tag "style", nonce: true
|
|
201
|
+
# # => <link href="/assets/style.css" rel="stylesheet" nonce="..." />
|
|
193
202
|
def stylesheet_link_tag(*sources)
|
|
194
203
|
options = sources.extract_options!.stringify_keys
|
|
195
204
|
path_options = options.extract!("protocol", "extname", "host", "skip_pipeline").symbolize_keys
|
|
@@ -197,7 +206,7 @@ module ActionView
|
|
|
197
206
|
preload_links = []
|
|
198
207
|
crossorigin = options.delete("crossorigin")
|
|
199
208
|
crossorigin = "anonymous" if crossorigin == true
|
|
200
|
-
nopush = options["nopush"].nil?
|
|
209
|
+
nopush = options["nopush"].nil? || options.delete("nopush")
|
|
201
210
|
integrity = options["integrity"]
|
|
202
211
|
|
|
203
212
|
sources_tags = sources.uniq.map { |source|
|
|
@@ -214,6 +223,9 @@ module ActionView
|
|
|
214
223
|
"crossorigin" => crossorigin,
|
|
215
224
|
"href" => href
|
|
216
225
|
}.merge!(options)
|
|
226
|
+
if tag_options["nonce"] == true
|
|
227
|
+
tag_options["nonce"] = content_security_policy_nonce
|
|
228
|
+
end
|
|
217
229
|
|
|
218
230
|
if apply_stylesheet_media_default && tag_options["media"].blank?
|
|
219
231
|
tag_options["media"] = "screen"
|
|
@@ -349,15 +361,15 @@ module ActionView
|
|
|
349
361
|
crossorigin = "anonymous" if crossorigin == true || (crossorigin.blank? && as_type == "font")
|
|
350
362
|
integrity = options[:integrity]
|
|
351
363
|
nopush = options.delete(:nopush) || false
|
|
352
|
-
rel = mime_type == "module" ? "modulepreload" : "preload"
|
|
364
|
+
rel = mime_type == "module" || mime_type == :module ? "modulepreload" : "preload"
|
|
353
365
|
|
|
354
|
-
link_tag = tag.link(
|
|
366
|
+
link_tag = tag.link(
|
|
355
367
|
rel: rel,
|
|
356
368
|
href: href,
|
|
357
369
|
as: as_type,
|
|
358
370
|
type: mime_type,
|
|
359
|
-
crossorigin: crossorigin
|
|
360
|
-
|
|
371
|
+
crossorigin: crossorigin,
|
|
372
|
+
**options.symbolize_keys)
|
|
361
373
|
|
|
362
374
|
preload_link = "<#{href}>; rel=#{rel}; as=#{as_type}"
|
|
363
375
|
preload_link += "; type=#{mime_type}" if mime_type
|
|
@@ -172,7 +172,7 @@ module ActionView
|
|
|
172
172
|
|
|
173
173
|
# Creates an entry tag for a specific record and prefills the id using class and id.
|
|
174
174
|
#
|
|
175
|
-
# Options
|
|
175
|
+
# ==== Options
|
|
176
176
|
#
|
|
177
177
|
# * <tt>:published</tt>: Time first published. Defaults to the created_at attribute on the record if one such exists.
|
|
178
178
|
# * <tt>:updated</tt>: Time of update. Defaults to the updated_at attribute on the record if one such exists.
|
|
@@ -189,7 +189,7 @@ module ActionView
|
|
|
189
189
|
CachingRegistry.caching?
|
|
190
190
|
end
|
|
191
191
|
|
|
192
|
-
# Raises
|
|
192
|
+
# Raises UncacheableFragmentError when called from within a +cache+ block.
|
|
193
193
|
#
|
|
194
194
|
# Useful to denote helper methods that can't participate in fragment caching:
|
|
195
195
|
#
|
|
@@ -198,7 +198,7 @@ module ActionView
|
|
|
198
198
|
# "#{project.name} - #{Time.now}"
|
|
199
199
|
# end
|
|
200
200
|
#
|
|
201
|
-
# # Which will then raise if used within a
|
|
201
|
+
# # Which will then raise if used within a `cache` block:
|
|
202
202
|
# <% cache project do %>
|
|
203
203
|
# <%= project_name_with_time(project) %>
|
|
204
204
|
# <% end %>
|
|
@@ -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
|
-
# +X-CSRF-Token+ HTTP header.
|
|
20
|
+
# +X-CSRF-Token+ HTTP header.
|
|
21
21
|
#
|
|
22
22
|
def csrf_meta_tags
|
|
23
23
|
if defined?(protect_against_forgery?) && protect_against_forgery?
|