actionview 6.0.0 → 6.1.0
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 +169 -162
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/action_view/base.rb +21 -52
- data/lib/action_view/cache_expiry.rb +1 -3
- data/lib/action_view/context.rb +0 -1
- data/lib/action_view/dependency_tracker.rb +10 -4
- data/lib/action_view/digestor.rb +3 -2
- data/lib/action_view/flows.rb +0 -1
- data/lib/action_view/gem_version.rb +1 -1
- data/lib/action_view/helpers/active_model_helper.rb +0 -1
- data/lib/action_view/helpers/asset_tag_helper.rb +41 -16
- 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 +11 -18
- data/lib/action_view/helpers/date_helper.rb +5 -6
- data/lib/action_view/helpers/form_helper.rb +61 -19
- data/lib/action_view/helpers/form_options_helper.rb +7 -16
- data/lib/action_view/helpers/form_tag_helper.rb +9 -7
- data/lib/action_view/helpers/javascript_helper.rb +7 -5
- data/lib/action_view/helpers/number_helper.rb +9 -8
- data/lib/action_view/helpers/rendering_helper.rb +11 -3
- data/lib/action_view/helpers/sanitize_helper.rb +2 -2
- data/lib/action_view/helpers/tag_helper.rb +94 -19
- data/lib/action_view/helpers/tags/base.rb +9 -6
- data/lib/action_view/helpers/tags/check_box.rb +0 -1
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +0 -1
- data/lib/action_view/helpers/tags/collection_helpers.rb +0 -1
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +0 -1
- data/lib/action_view/helpers/tags/color_field.rb +0 -1
- data/lib/action_view/helpers/tags/date_field.rb +1 -2
- data/lib/action_view/helpers/tags/date_select.rb +2 -3
- data/lib/action_view/helpers/tags/datetime_field.rb +0 -1
- data/lib/action_view/helpers/tags/datetime_local_field.rb +1 -2
- data/lib/action_view/helpers/tags/label.rb +4 -1
- data/lib/action_view/helpers/tags/month_field.rb +1 -2
- data/lib/action_view/helpers/tags/radio_button.rb +0 -1
- data/lib/action_view/helpers/tags/select.rb +1 -2
- data/lib/action_view/helpers/tags/text_field.rb +0 -1
- data/lib/action_view/helpers/tags/time_field.rb +1 -2
- data/lib/action_view/helpers/tags/week_field.rb +1 -2
- data/lib/action_view/helpers/text_helper.rb +1 -2
- data/lib/action_view/helpers/translation_helper.rb +98 -53
- data/lib/action_view/helpers/url_helper.rb +107 -13
- data/lib/action_view/layouts.rb +3 -5
- data/lib/action_view/log_subscriber.rb +26 -11
- data/lib/action_view/lookup_context.rb +7 -21
- data/lib/action_view/path_set.rb +0 -4
- data/lib/action_view/railtie.rb +35 -46
- data/lib/action_view/record_identifier.rb +0 -1
- data/lib/action_view/renderer/abstract_renderer.rb +92 -14
- data/lib/action_view/renderer/collection_renderer.rb +192 -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 -283
- data/lib/action_view/renderer/renderer.rb +44 -1
- data/lib/action_view/renderer/streaming_template_renderer.rb +5 -3
- data/lib/action_view/renderer/template_renderer.rb +16 -14
- data/lib/action_view/rendering.rb +3 -2
- data/lib/action_view/routing_url_for.rb +1 -1
- data/lib/action_view/template/error.rb +9 -14
- data/lib/action_view/template/handlers/erb/erubi.rb +9 -7
- data/lib/action_view/template/handlers/erb.rb +10 -15
- 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 +83 -45
- data/lib/action_view/template/text.rb +0 -3
- data/lib/action_view/template.rb +9 -50
- data/lib/action_view/test_case.rb +20 -28
- data/lib/action_view/testing/resolvers.rb +10 -32
- data/lib/action_view/unbound_template.rb +4 -5
- data/lib/action_view/view_paths.rb +34 -37
- data/lib/action_view.rb +5 -1
- data/lib/assets/compiled/rails-ujs.js +3 -3
- metadata +17 -11
|
@@ -81,19 +81,19 @@ module ActionView
|
|
|
81
81
|
end
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
def source_extract(indentation = 0
|
|
85
|
-
return unless num = line_number
|
|
84
|
+
def source_extract(indentation = 0)
|
|
85
|
+
return [] unless num = line_number
|
|
86
86
|
num = num.to_i
|
|
87
87
|
|
|
88
|
-
source_code = @template.
|
|
88
|
+
source_code = @template.encode!.split("\n")
|
|
89
89
|
|
|
90
90
|
start_on_line = [ num - SOURCE_CODE_RADIUS - 1, 0 ].max
|
|
91
91
|
end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min
|
|
92
92
|
|
|
93
93
|
indent = end_on_line.to_s.size + indentation
|
|
94
|
-
return unless source_code = source_code[start_on_line..end_on_line]
|
|
94
|
+
return [] unless source_code = source_code[start_on_line..end_on_line]
|
|
95
95
|
|
|
96
|
-
formatted_code_for(source_code, start_on_line, indent
|
|
96
|
+
formatted_code_for(source_code, start_on_line, indent)
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
def sub_template_of(template_path)
|
|
@@ -114,7 +114,6 @@ module ActionView
|
|
|
114
114
|
end
|
|
115
115
|
|
|
116
116
|
private
|
|
117
|
-
|
|
118
117
|
def source_location
|
|
119
118
|
if line_number
|
|
120
119
|
"on line ##{line_number} of "
|
|
@@ -123,15 +122,11 @@ module ActionView
|
|
|
123
122
|
end + file_name
|
|
124
123
|
end
|
|
125
124
|
|
|
126
|
-
def formatted_code_for(source_code, line_counter, indent
|
|
127
|
-
|
|
128
|
-
source_code.
|
|
125
|
+
def formatted_code_for(source_code, line_counter, indent)
|
|
126
|
+
indent_template = "%#{indent}s: %s"
|
|
127
|
+
source_code.map do |line|
|
|
129
128
|
line_counter += 1
|
|
130
|
-
|
|
131
|
-
result.update(line_counter.to_s => "%#{indent}s %s\n" % ["", line])
|
|
132
|
-
else
|
|
133
|
-
result << "%#{indent}s: %s" % [line_counter, line]
|
|
134
|
-
end
|
|
129
|
+
indent_template % [line_counter, line]
|
|
135
130
|
end
|
|
136
131
|
end
|
|
137
132
|
end
|
|
@@ -13,9 +13,11 @@ module ActionView
|
|
|
13
13
|
|
|
14
14
|
# Dup properties so that we don't modify argument
|
|
15
15
|
properties = Hash[properties]
|
|
16
|
-
|
|
17
|
-
properties[:
|
|
18
|
-
properties[:
|
|
16
|
+
|
|
17
|
+
properties[:bufvar] ||= "@output_buffer"
|
|
18
|
+
properties[:preamble] ||= ""
|
|
19
|
+
properties[:postamble] ||= "#{properties[:bufvar]}.to_s"
|
|
20
|
+
|
|
19
21
|
properties[:escapefunc] = ""
|
|
20
22
|
|
|
21
23
|
super
|
|
@@ -37,7 +39,7 @@ module ActionView
|
|
|
37
39
|
if text == "\n"
|
|
38
40
|
@newline_pending += 1
|
|
39
41
|
else
|
|
40
|
-
src << "
|
|
42
|
+
src << bufvar << ".safe_append='"
|
|
41
43
|
src << "\n" * @newline_pending if @newline_pending > 0
|
|
42
44
|
src << text.gsub(/['\\]/, '\\\\\&')
|
|
43
45
|
src << "'.freeze;"
|
|
@@ -52,9 +54,9 @@ module ActionView
|
|
|
52
54
|
flush_newline_if_pending(src)
|
|
53
55
|
|
|
54
56
|
if (indicator == "==") || @escape
|
|
55
|
-
src << "
|
|
57
|
+
src << bufvar << ".safe_expr_append="
|
|
56
58
|
else
|
|
57
|
-
src << "
|
|
59
|
+
src << bufvar << ".append="
|
|
58
60
|
end
|
|
59
61
|
|
|
60
62
|
if BLOCK_EXPR.match?(code)
|
|
@@ -76,7 +78,7 @@ module ActionView
|
|
|
76
78
|
|
|
77
79
|
def flush_newline_if_pending(src)
|
|
78
80
|
if @newline_pending > 0
|
|
79
|
-
src << "
|
|
81
|
+
src << bufvar << ".safe_append='#{"\n" * @newline_pending}'.freeze;"
|
|
80
82
|
@newline_pending = 0
|
|
81
83
|
end
|
|
82
84
|
end
|
|
@@ -16,16 +16,6 @@ module ActionView
|
|
|
16
16
|
# Do not escape templates of these mime types.
|
|
17
17
|
class_attribute :escape_ignore_list, default: ["text/plain"]
|
|
18
18
|
|
|
19
|
-
[self, singleton_class].each do |base|
|
|
20
|
-
base.alias_method :escape_whitelist, :escape_ignore_list
|
|
21
|
-
base.alias_method :escape_whitelist=, :escape_ignore_list=
|
|
22
|
-
|
|
23
|
-
base.deprecate(
|
|
24
|
-
escape_whitelist: "use #escape_ignore_list instead",
|
|
25
|
-
:escape_whitelist= => "use #escape_ignore_list= instead"
|
|
26
|
-
)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
19
|
ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")
|
|
30
20
|
|
|
31
21
|
def self.call(template, source)
|
|
@@ -45,7 +35,7 @@ module ActionView
|
|
|
45
35
|
# wrong, we can still find an encoding tag
|
|
46
36
|
# (<%# encoding %>) inside the String using a regular
|
|
47
37
|
# expression
|
|
48
|
-
template_source = source.
|
|
38
|
+
template_source = source.b
|
|
49
39
|
|
|
50
40
|
erb = template_source.gsub(ENCODING_TAG, "")
|
|
51
41
|
encoding = $2
|
|
@@ -55,15 +45,20 @@ module ActionView
|
|
|
55
45
|
# Always make sure we return a String in the default_internal
|
|
56
46
|
erb.encode!
|
|
57
47
|
|
|
58
|
-
|
|
59
|
-
erb,
|
|
48
|
+
options = {
|
|
60
49
|
escape: (self.class.escape_ignore_list.include? template.type),
|
|
61
50
|
trim: (self.class.erb_trim_mode == "-")
|
|
62
|
-
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if ActionView::Base.annotate_rendered_view_with_filenames && template.format == :html
|
|
54
|
+
options[:preamble] = "@output_buffer.safe_append='<!-- BEGIN #{template.short_identifier} -->';"
|
|
55
|
+
options[:postamble] = "@output_buffer.safe_append='<!-- END #{template.short_identifier} -->';@output_buffer.to_s"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
self.class.erb_implementation.new(erb, options).src
|
|
63
59
|
end
|
|
64
60
|
|
|
65
61
|
private
|
|
66
|
-
|
|
67
62
|
def valid_encoding(string, encoding)
|
|
68
63
|
# If a magic encoding comment was found, tag the
|
|
69
64
|
# String with this encoding. This is for a case
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "active_support/deprecation"
|
|
4
|
-
|
|
5
3
|
module ActionView #:nodoc:
|
|
6
4
|
# = Action View Template Handlers
|
|
7
5
|
class Template #:nodoc:
|
|
@@ -26,35 +24,11 @@ module ActionView #:nodoc:
|
|
|
26
24
|
@@template_extensions ||= @@template_handlers.keys
|
|
27
25
|
end
|
|
28
26
|
|
|
29
|
-
class LegacyHandlerWrapper < SimpleDelegator # :nodoc:
|
|
30
|
-
def call(view, source)
|
|
31
|
-
__getobj__.call(ActionView::Template::LegacyTemplate.new(view, source))
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
27
|
# Register an object that knows how to handle template files with the given
|
|
36
28
|
# extensions. This can be used to implement new template types.
|
|
37
29
|
# The handler must respond to +:call+, which will be passed the template
|
|
38
30
|
# and should return the rendered template as a String.
|
|
39
31
|
def register_template_handler(*extensions, handler)
|
|
40
|
-
params = if handler.is_a?(Proc)
|
|
41
|
-
handler.parameters
|
|
42
|
-
else
|
|
43
|
-
handler.method(:call).parameters
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
unless params.find_all { |type, _| type == :req || type == :opt }.length >= 2
|
|
47
|
-
ActiveSupport::Deprecation.warn <<~eowarn
|
|
48
|
-
Single arity template handlers are deprecated. Template handlers must
|
|
49
|
-
now accept two parameters, the view object and the source for the view object.
|
|
50
|
-
Change:
|
|
51
|
-
>> #{handler}.call(#{params.map(&:last).join(", ")})
|
|
52
|
-
To:
|
|
53
|
-
>> #{handler}.call(#{params.map(&:last).join(", ")}, source)
|
|
54
|
-
eowarn
|
|
55
|
-
handler = LegacyHandlerWrapper.new(handler)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
32
|
raise(ArgumentError, "Extension is required") if extensions.empty?
|
|
59
33
|
extensions.each do |extension|
|
|
60
34
|
@@template_handlers[extension.to_sym] = handler
|
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "active_support/deprecation"
|
|
4
|
-
|
|
5
3
|
module ActionView #:nodoc:
|
|
6
4
|
# = Action View HTML Template
|
|
7
5
|
class Template #:nodoc:
|
|
8
6
|
class HTML #:nodoc:
|
|
9
7
|
attr_reader :type
|
|
10
8
|
|
|
11
|
-
def initialize(string, type
|
|
12
|
-
unless type
|
|
13
|
-
ActiveSupport::Deprecation.warn "ActionView::Template::HTML#initialize requires a type parameter"
|
|
14
|
-
type = :html
|
|
15
|
-
end
|
|
16
|
-
|
|
9
|
+
def initialize(string, type)
|
|
17
10
|
@string = string.to_s
|
|
18
11
|
@type = type
|
|
19
12
|
end
|
|
@@ -35,9 +28,6 @@ module ActionView #:nodoc:
|
|
|
35
28
|
def format
|
|
36
29
|
@type
|
|
37
30
|
end
|
|
38
|
-
|
|
39
|
-
def formats; Array(format); end
|
|
40
|
-
deprecate :formats
|
|
41
31
|
end
|
|
42
32
|
end
|
|
43
33
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActionView
|
|
4
|
+
# = Action View Renderable Template for objects that respond to #render_in
|
|
5
|
+
class Template
|
|
6
|
+
class Renderable # :nodoc:
|
|
7
|
+
def initialize(renderable)
|
|
8
|
+
@renderable = renderable
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def identifier
|
|
12
|
+
@renderable.class.name
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def render(context, *args)
|
|
16
|
+
@renderable.render_in(context)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def format
|
|
20
|
+
@renderable.format
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -35,6 +35,41 @@ module ActionView
|
|
|
35
35
|
alias :to_s :to_str
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
class PathParser # :nodoc:
|
|
39
|
+
def build_path_regex
|
|
40
|
+
handlers = Template::Handlers.extensions.map { |x| Regexp.escape(x) }.join("|")
|
|
41
|
+
formats = Template::Types.symbols.map { |x| Regexp.escape(x) }.join("|")
|
|
42
|
+
locales = "[a-z]{2}(?:-[A-Z]{2})?"
|
|
43
|
+
variants = "[^.]*"
|
|
44
|
+
|
|
45
|
+
%r{
|
|
46
|
+
\A
|
|
47
|
+
(?:(?<prefix>.*)/)?
|
|
48
|
+
(?<partial>_)?
|
|
49
|
+
(?<action>.*?)
|
|
50
|
+
(?:\.(?<locale>#{locales}))??
|
|
51
|
+
(?:\.(?<format>#{formats}))??
|
|
52
|
+
(?:\+(?<variant>#{variants}))??
|
|
53
|
+
(?:\.(?<handler>#{handlers}))?
|
|
54
|
+
\z
|
|
55
|
+
}x
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def parse(path)
|
|
59
|
+
@regex ||= build_path_regex
|
|
60
|
+
match = @regex.match(path)
|
|
61
|
+
{
|
|
62
|
+
prefix: match[:prefix] || "",
|
|
63
|
+
action: match[:action],
|
|
64
|
+
partial: !!match[:partial],
|
|
65
|
+
locale: match[:locale]&.to_sym,
|
|
66
|
+
handler: match[:handler]&.to_sym,
|
|
67
|
+
format: match[:format]&.to_sym,
|
|
68
|
+
variant: match[:variant]
|
|
69
|
+
}
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
38
73
|
# Threadsafe template cache
|
|
39
74
|
class Cache #:nodoc:
|
|
40
75
|
class SmallCache < Concurrent::Map
|
|
@@ -43,13 +78,13 @@ module ActionView
|
|
|
43
78
|
end
|
|
44
79
|
end
|
|
45
80
|
|
|
46
|
-
#
|
|
81
|
+
# Preallocate all the default blocks for performance/memory consumption reasons
|
|
47
82
|
PARTIAL_BLOCK = lambda { |cache, partial| cache[partial] = SmallCache.new }
|
|
48
83
|
PREFIX_BLOCK = lambda { |cache, prefix| cache[prefix] = SmallCache.new(&PARTIAL_BLOCK) }
|
|
49
84
|
NAME_BLOCK = lambda { |cache, name| cache[name] = SmallCache.new(&PREFIX_BLOCK) }
|
|
50
85
|
KEY_BLOCK = lambda { |cache, key| cache[key] = SmallCache.new(&NAME_BLOCK) }
|
|
51
86
|
|
|
52
|
-
#
|
|
87
|
+
# Usually a majority of template look ups return nothing, use this canonical preallocated array to save memory
|
|
53
88
|
NO_TEMPLATES = [].freeze
|
|
54
89
|
|
|
55
90
|
def initialize
|
|
@@ -58,7 +93,7 @@ module ActionView
|
|
|
58
93
|
end
|
|
59
94
|
|
|
60
95
|
def inspect
|
|
61
|
-
"
|
|
96
|
+
"#{to_s[0..-2]} keys=#{@data.size} queries=#{@query_cache.size}>"
|
|
62
97
|
end
|
|
63
98
|
|
|
64
99
|
# Cache the templates returned by the block
|
|
@@ -75,7 +110,7 @@ module ActionView
|
|
|
75
110
|
@query_cache.clear
|
|
76
111
|
end
|
|
77
112
|
|
|
78
|
-
# Get the cache size.
|
|
113
|
+
# Get the cache size. Do not call this
|
|
79
114
|
# method. This method is not guaranteed to be here ever.
|
|
80
115
|
def size # :nodoc:
|
|
81
116
|
size = 0
|
|
@@ -93,7 +128,6 @@ module ActionView
|
|
|
93
128
|
end
|
|
94
129
|
|
|
95
130
|
private
|
|
96
|
-
|
|
97
131
|
def canonical_no_templates(templates)
|
|
98
132
|
templates.empty? ? NO_TEMPLATES : templates
|
|
99
133
|
end
|
|
@@ -122,15 +156,11 @@ module ActionView
|
|
|
122
156
|
end
|
|
123
157
|
end
|
|
124
158
|
|
|
125
|
-
alias :find_all_anywhere :find_all
|
|
126
|
-
deprecate :find_all_anywhere
|
|
127
|
-
|
|
128
159
|
def find_all_with_query(query) # :nodoc:
|
|
129
160
|
@cache.cache_query(query) { find_template_paths(File.join(@path, query)) }
|
|
130
161
|
end
|
|
131
162
|
|
|
132
163
|
private
|
|
133
|
-
|
|
134
164
|
def _find_all(name, prefix, partial, details, key, locals)
|
|
135
165
|
find_templates(name, prefix, partial, details, locals)
|
|
136
166
|
end
|
|
@@ -166,24 +196,20 @@ module ActionView
|
|
|
166
196
|
EXTENSIONS = { locale: ".", formats: ".", variants: "+", handlers: "." }
|
|
167
197
|
DEFAULT_PATTERN = ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}"
|
|
168
198
|
|
|
169
|
-
def initialize
|
|
170
|
-
|
|
171
|
-
ActiveSupport::Deprecation.warn "Specifying a custom path for #{self.class} is deprecated. Implement a custom Resolver subclass instead."
|
|
172
|
-
@pattern = pattern
|
|
173
|
-
else
|
|
174
|
-
@pattern = DEFAULT_PATTERN
|
|
175
|
-
end
|
|
199
|
+
def initialize
|
|
200
|
+
@pattern = DEFAULT_PATTERN
|
|
176
201
|
@unbound_templates = Concurrent::Map.new
|
|
177
|
-
|
|
202
|
+
@path_parser = PathParser.new
|
|
203
|
+
super
|
|
178
204
|
end
|
|
179
205
|
|
|
180
206
|
def clear_cache
|
|
181
207
|
@unbound_templates.clear
|
|
182
|
-
|
|
208
|
+
@path_parser = PathParser.new
|
|
209
|
+
super
|
|
183
210
|
end
|
|
184
211
|
|
|
185
212
|
private
|
|
186
|
-
|
|
187
213
|
def _find_all(name, prefix, partial, details, key, locals)
|
|
188
214
|
path = Path.build(name, prefix, partial)
|
|
189
215
|
query(path, details, details[:formats], locals, cache: !!key)
|
|
@@ -207,9 +233,13 @@ module ActionView
|
|
|
207
233
|
end
|
|
208
234
|
end
|
|
209
235
|
|
|
236
|
+
def source_for_template(template)
|
|
237
|
+
Template::Sources::File.new(template)
|
|
238
|
+
end
|
|
239
|
+
|
|
210
240
|
def build_unbound_template(template, virtual_path)
|
|
211
241
|
handler, format, variant = extract_handler_and_format_and_variant(template)
|
|
212
|
-
source =
|
|
242
|
+
source = source_for_template(template)
|
|
213
243
|
|
|
214
244
|
UnboundTemplate.new(
|
|
215
245
|
source,
|
|
@@ -226,6 +256,10 @@ module ActionView
|
|
|
226
256
|
end
|
|
227
257
|
|
|
228
258
|
def find_template_paths_from_details(path, details)
|
|
259
|
+
if path.name.include?(".")
|
|
260
|
+
ActiveSupport::Deprecation.warn("Rendering actions with '.' in the name is deprecated: #{path}")
|
|
261
|
+
end
|
|
262
|
+
|
|
229
263
|
query = build_query(path, details)
|
|
230
264
|
find_template_paths(query)
|
|
231
265
|
end
|
|
@@ -252,7 +286,7 @@ module ActionView
|
|
|
252
286
|
query.gsub!(/:prefix(\/)?/, prefix)
|
|
253
287
|
|
|
254
288
|
partial = escape_entry(path.partial? ? "_#{path.name}" : path.name)
|
|
255
|
-
query.gsub!(
|
|
289
|
+
query.gsub!(":action", partial)
|
|
256
290
|
|
|
257
291
|
details.each do |ext, candidates|
|
|
258
292
|
if ext == :variants && candidates == :any
|
|
@@ -273,22 +307,11 @@ module ActionView
|
|
|
273
307
|
# from the path, or the handler, we should return the array of formats given
|
|
274
308
|
# to the resolver.
|
|
275
309
|
def extract_handler_and_format_and_variant(path)
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
handler = Template.handler_for_extension(extension)
|
|
282
|
-
format, variant = pieces.last.split(EXTENSIONS[:variants], 2) if pieces.last
|
|
283
|
-
format = if format
|
|
284
|
-
Template::Types[format]&.ref
|
|
285
|
-
else
|
|
286
|
-
if handler.respond_to?(:default_format) # default_format can return nil
|
|
287
|
-
handler.default_format
|
|
288
|
-
else
|
|
289
|
-
nil
|
|
290
|
-
end
|
|
291
|
-
end
|
|
310
|
+
details = @path_parser.parse(path)
|
|
311
|
+
|
|
312
|
+
handler = Template.handler_for_extension(details[:handler])
|
|
313
|
+
format = details[:format] || handler.try(:default_format)
|
|
314
|
+
variant = details[:variant]
|
|
292
315
|
|
|
293
316
|
# Template::Types[format] and handler.default_format can return nil
|
|
294
317
|
[handler, format, variant]
|
|
@@ -299,9 +322,9 @@ module ActionView
|
|
|
299
322
|
class FileSystemResolver < PathResolver
|
|
300
323
|
attr_reader :path
|
|
301
324
|
|
|
302
|
-
def initialize(path
|
|
325
|
+
def initialize(path)
|
|
303
326
|
raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
|
|
304
|
-
super(
|
|
327
|
+
super()
|
|
305
328
|
@path = File.expand_path(path)
|
|
306
329
|
end
|
|
307
330
|
|
|
@@ -323,15 +346,27 @@ module ActionView
|
|
|
323
346
|
end
|
|
324
347
|
|
|
325
348
|
private
|
|
326
|
-
|
|
327
|
-
def find_template_paths_from_details(path, details)
|
|
349
|
+
def find_candidate_template_paths(path)
|
|
328
350
|
# Instead of checking for every possible path, as our other globs would
|
|
329
351
|
# do, scan the directory for files with the right prefix.
|
|
330
352
|
query = "#{escape_entry(File.join(@path, path))}*"
|
|
331
353
|
|
|
354
|
+
Dir[query].reject do |filename|
|
|
355
|
+
File.directory?(filename)
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def find_template_paths_from_details(path, details)
|
|
360
|
+
if path.name.include?(".")
|
|
361
|
+
# Fall back to the unoptimized resolver, which will warn
|
|
362
|
+
return super
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
candidates = find_candidate_template_paths(path)
|
|
366
|
+
|
|
332
367
|
regex = build_regex(path, details)
|
|
333
368
|
|
|
334
|
-
|
|
369
|
+
candidates.uniq.reject do |filename|
|
|
335
370
|
# This regex match does double duty of finding only files which match
|
|
336
371
|
# details (instead of just matching the prefix) and also filtering for
|
|
337
372
|
# case-insensitive file systems.
|
|
@@ -343,7 +378,7 @@ module ActionView
|
|
|
343
378
|
# We can use the matches found by the regex and sort by their index in
|
|
344
379
|
# details.
|
|
345
380
|
match = filename.match(regex)
|
|
346
|
-
EXTENSIONS.keys.
|
|
381
|
+
EXTENSIONS.keys.map do |ext|
|
|
347
382
|
if ext == :variants && details[ext] == :any
|
|
348
383
|
match[ext].nil? ? 0 : 1
|
|
349
384
|
elsif match[ext].nil?
|
|
@@ -358,13 +393,16 @@ module ActionView
|
|
|
358
393
|
end
|
|
359
394
|
|
|
360
395
|
def build_regex(path, details)
|
|
361
|
-
query =
|
|
396
|
+
query = Regexp.escape(File.join(@path, path))
|
|
362
397
|
exts = EXTENSIONS.map do |ext, prefix|
|
|
363
398
|
match =
|
|
364
399
|
if ext == :variants && details[ext] == :any
|
|
365
400
|
".*?"
|
|
366
401
|
else
|
|
367
|
-
details[ext].compact
|
|
402
|
+
arr = details[ext].compact
|
|
403
|
+
arr.uniq!
|
|
404
|
+
arr.map! { |e| Regexp.escape(e) }
|
|
405
|
+
arr.join("|")
|
|
368
406
|
end
|
|
369
407
|
prefix = Regexp.escape(prefix)
|
|
370
408
|
"(#{prefix}(?<#{ext}>#{match}))?"
|
data/lib/action_view/template.rb
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "active_support/core_ext/object/try"
|
|
4
|
-
require "active_support/core_ext/kernel/singleton_class"
|
|
5
|
-
require "active_support/deprecation"
|
|
6
3
|
require "thread"
|
|
7
4
|
require "delegate"
|
|
8
5
|
|
|
@@ -11,14 +8,6 @@ module ActionView
|
|
|
11
8
|
class Template
|
|
12
9
|
extend ActiveSupport::Autoload
|
|
13
10
|
|
|
14
|
-
def self.finalize_compiled_template_methods
|
|
15
|
-
ActiveSupport::Deprecation.warn "ActionView::Template.finalize_compiled_template_methods is deprecated and has no effect"
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def self.finalize_compiled_template_methods=(_)
|
|
19
|
-
ActiveSupport::Deprecation.warn "ActionView::Template.finalize_compiled_template_methods= is deprecated and has no effect"
|
|
20
|
-
end
|
|
21
|
-
|
|
22
11
|
# === Encodings in ActionView::Template
|
|
23
12
|
#
|
|
24
13
|
# ActionView::Template is one of a few sources of potential
|
|
@@ -114,6 +103,7 @@ module ActionView
|
|
|
114
103
|
eager_autoload do
|
|
115
104
|
autoload :Error
|
|
116
105
|
autoload :RawFile
|
|
106
|
+
autoload :Renderable
|
|
117
107
|
autoload :Handlers
|
|
118
108
|
autoload :HTML
|
|
119
109
|
autoload :Inline
|
|
@@ -124,15 +114,10 @@ module ActionView
|
|
|
124
114
|
|
|
125
115
|
extend Template::Handlers
|
|
126
116
|
|
|
127
|
-
attr_reader :identifier, :handler
|
|
117
|
+
attr_reader :identifier, :handler
|
|
128
118
|
attr_reader :variable, :format, :variant, :locals, :virtual_path
|
|
129
119
|
|
|
130
|
-
def initialize(source, identifier, handler, format: nil, variant: nil,
|
|
131
|
-
unless locals
|
|
132
|
-
ActiveSupport::Deprecation.warn "ActionView::Template#initialize requires a locals parameter"
|
|
133
|
-
locals = []
|
|
134
|
-
end
|
|
135
|
-
|
|
120
|
+
def initialize(source, identifier, handler, locals:, format: nil, variant: nil, virtual_path: nil)
|
|
136
121
|
@source = source
|
|
137
122
|
@identifier = identifier
|
|
138
123
|
@handler = handler
|
|
@@ -141,32 +126,16 @@ module ActionView
|
|
|
141
126
|
@virtual_path = virtual_path
|
|
142
127
|
|
|
143
128
|
@variable = if @virtual_path
|
|
144
|
-
base = @virtual_path
|
|
129
|
+
base = @virtual_path.end_with?("/") ? "" : ::File.basename(@virtual_path)
|
|
145
130
|
base =~ /\A_?(.*?)(?:\.\w+)*\z/
|
|
146
131
|
$1.to_sym
|
|
147
132
|
end
|
|
148
133
|
|
|
149
|
-
if updated_at
|
|
150
|
-
ActiveSupport::Deprecation.warn "ActionView::Template#updated_at is deprecated"
|
|
151
|
-
@updated_at = updated_at
|
|
152
|
-
else
|
|
153
|
-
@updated_at = Time.now
|
|
154
|
-
end
|
|
155
134
|
@format = format
|
|
156
135
|
@variant = variant
|
|
157
136
|
@compile_mutex = Mutex.new
|
|
158
137
|
end
|
|
159
138
|
|
|
160
|
-
deprecate :original_encoding
|
|
161
|
-
deprecate :updated_at
|
|
162
|
-
deprecate def virtual_path=(_); end
|
|
163
|
-
deprecate def locals=(_); end
|
|
164
|
-
deprecate def formats=(_); end
|
|
165
|
-
deprecate def formats; Array(format); end
|
|
166
|
-
deprecate def variants=(_); end
|
|
167
|
-
deprecate def variants; [variant]; end
|
|
168
|
-
deprecate def refresh(_); self; end
|
|
169
|
-
|
|
170
139
|
# Returns whether the underlying handler supports streaming. If so,
|
|
171
140
|
# a streaming buffer *may* be passed when it starts rendering.
|
|
172
141
|
def supports_streaming?
|
|
@@ -179,10 +148,10 @@ module ActionView
|
|
|
179
148
|
# This method is instrumented as "!render_template.action_view". Notice that
|
|
180
149
|
# we use a bang in this instrumentation because you don't want to
|
|
181
150
|
# consume this in production. This is only slow if it's being listened to.
|
|
182
|
-
def render(view, locals, buffer = ActionView::OutputBuffer.new, &block)
|
|
151
|
+
def render(view, locals, buffer = ActionView::OutputBuffer.new, add_to_stack: true, &block)
|
|
183
152
|
instrument_render_template do
|
|
184
153
|
compile!(view)
|
|
185
|
-
view._run(method_name, self, locals, buffer, &block)
|
|
154
|
+
view._run(method_name, self, locals, buffer, add_to_stack: add_to_stack, &block)
|
|
186
155
|
end
|
|
187
156
|
rescue => e
|
|
188
157
|
handle_render_error(view, e)
|
|
@@ -193,7 +162,7 @@ module ActionView
|
|
|
193
162
|
end
|
|
194
163
|
|
|
195
164
|
def short_identifier
|
|
196
|
-
@short_identifier ||= defined?(Rails.root) ? identifier.
|
|
165
|
+
@short_identifier ||= defined?(Rails.root) ? identifier.delete_prefix("#{Rails.root}/") : identifier
|
|
197
166
|
end
|
|
198
167
|
|
|
199
168
|
def inspect
|
|
@@ -255,16 +224,15 @@ module ActionView
|
|
|
255
224
|
# to ensure that references to the template object can be marshalled as well. This means forgoing
|
|
256
225
|
# the marshalling of the compiler mutex and instantiating that again on unmarshalling.
|
|
257
226
|
def marshal_dump # :nodoc:
|
|
258
|
-
[ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @
|
|
227
|
+
[ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant ]
|
|
259
228
|
end
|
|
260
229
|
|
|
261
230
|
def marshal_load(array) # :nodoc:
|
|
262
|
-
@source, @identifier, @handler, @compiled, @locals, @virtual_path, @
|
|
231
|
+
@source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant = *array
|
|
263
232
|
@compile_mutex = Mutex.new
|
|
264
233
|
end
|
|
265
234
|
|
|
266
235
|
private
|
|
267
|
-
|
|
268
236
|
# Compile a template. This method ensures a template is compiled
|
|
269
237
|
# just once and removes the source after it is compiled.
|
|
270
238
|
def compile!(view)
|
|
@@ -289,15 +257,6 @@ module ActionView
|
|
|
289
257
|
end
|
|
290
258
|
end
|
|
291
259
|
|
|
292
|
-
class LegacyTemplate < DelegateClass(Template) # :nodoc:
|
|
293
|
-
attr_reader :source
|
|
294
|
-
|
|
295
|
-
def initialize(template, source)
|
|
296
|
-
super(template)
|
|
297
|
-
@source = source
|
|
298
|
-
end
|
|
299
|
-
end
|
|
300
|
-
|
|
301
260
|
# Among other things, this method is responsible for properly setting
|
|
302
261
|
# the encoding of the compiled template.
|
|
303
262
|
#
|