actionview 4.2.11 → 5.0.7
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionview might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +304 -184
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -3
- data/lib/action_view.rb +1 -1
- data/lib/action_view/base.rb +14 -2
- data/lib/action_view/dependency_tracker.rb +51 -18
- data/lib/action_view/digestor.rb +83 -81
- data/lib/action_view/flows.rb +4 -5
- data/lib/action_view/gem_version.rb +3 -3
- data/lib/action_view/helpers/asset_tag_helper.rb +15 -5
- data/lib/action_view/helpers/asset_url_helper.rb +51 -12
- data/lib/action_view/helpers/atom_feed_helper.rb +6 -5
- data/lib/action_view/helpers/cache_helper.rb +62 -21
- data/lib/action_view/helpers/capture_helper.rb +5 -4
- data/lib/action_view/helpers/controller_helper.rb +11 -2
- data/lib/action_view/helpers/date_helper.rb +59 -13
- data/lib/action_view/helpers/debug_helper.rb +1 -1
- data/lib/action_view/helpers/form_helper.rb +74 -72
- data/lib/action_view/helpers/form_options_helper.rb +79 -39
- data/lib/action_view/helpers/form_tag_helper.rb +74 -44
- data/lib/action_view/helpers/javascript_helper.rb +4 -4
- data/lib/action_view/helpers/number_helper.rb +28 -13
- data/lib/action_view/helpers/output_safety_helper.rb +32 -2
- data/lib/action_view/helpers/record_tag_helper.rb +12 -99
- data/lib/action_view/helpers/rendering_helper.rb +2 -2
- data/lib/action_view/helpers/sanitize_helper.rb +1 -2
- data/lib/action_view/helpers/tag_helper.rb +19 -11
- data/lib/action_view/helpers/tags/base.rb +45 -29
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +4 -28
- data/lib/action_view/helpers/tags/collection_helpers.rb +32 -0
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +1 -9
- data/lib/action_view/helpers/tags/datetime_field.rb +1 -1
- data/lib/action_view/helpers/tags/label.rb +1 -1
- data/lib/action_view/helpers/tags/placeholderable.rb +1 -1
- data/lib/action_view/helpers/tags/search_field.rb +12 -9
- data/lib/action_view/helpers/tags/text_field.rb +0 -1
- data/lib/action_view/helpers/tags/translator.rb +1 -1
- data/lib/action_view/helpers/text_helper.rb +27 -11
- data/lib/action_view/helpers/translation_helper.rb +56 -26
- data/lib/action_view/helpers/url_helper.rb +108 -79
- data/lib/action_view/layouts.rb +11 -10
- data/lib/action_view/log_subscriber.rb +35 -1
- data/lib/action_view/lookup_context.rb +69 -48
- data/lib/action_view/model_naming.rb +1 -1
- data/lib/action_view/path_set.rb +9 -0
- data/lib/action_view/railtie.rb +18 -3
- data/lib/action_view/record_identifier.rb +45 -19
- data/lib/action_view/renderer/abstract_renderer.rb +7 -3
- data/lib/action_view/renderer/partial_renderer.rb +38 -37
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +49 -0
- data/lib/action_view/renderer/renderer.rb +2 -6
- data/lib/action_view/renderer/streaming_template_renderer.rb +1 -1
- data/lib/action_view/renderer/template_renderer.rb +11 -10
- data/lib/action_view/rendering.rb +15 -7
- data/lib/action_view/routing_url_for.rb +18 -6
- data/lib/action_view/tasks/{dependencies.rake → cache_digests.rake} +2 -2
- data/lib/action_view/template.rb +36 -12
- data/lib/action_view/template/error.rb +20 -9
- data/lib/action_view/template/handlers.rb +6 -4
- data/lib/action_view/template/handlers/html.rb +9 -0
- data/lib/action_view/template/handlers/raw.rb +1 -3
- data/lib/action_view/template/resolver.rb +49 -42
- data/lib/action_view/template/types.rb +14 -16
- data/lib/action_view/test_case.rb +15 -9
- data/lib/action_view/testing/resolvers.rb +1 -2
- data/lib/action_view/view_paths.rb +6 -24
- metadata +16 -20
@@ -2,13 +2,13 @@ namespace :cache_digests do
|
|
2
2
|
desc 'Lookup nested dependencies for TEMPLATE (like messages/show or comments/_comment.html)'
|
3
3
|
task :nested_dependencies => :environment do
|
4
4
|
abort 'You must provide TEMPLATE for the task to run' unless ENV['TEMPLATE'].present?
|
5
|
-
puts JSON.pretty_generate ActionView::Digestor.
|
5
|
+
puts JSON.pretty_generate ActionView::Digestor.tree(CacheDigests.template_name, CacheDigests.finder).children.map(&:to_dep_map)
|
6
6
|
end
|
7
7
|
|
8
8
|
desc 'Lookup first-level dependencies for TEMPLATE (like messages/show or comments/_comment.html)'
|
9
9
|
task :dependencies => :environment do
|
10
10
|
abort 'You must provide TEMPLATE for the task to run' unless ENV['TEMPLATE'].present?
|
11
|
-
puts JSON.pretty_generate ActionView::Digestor.
|
11
|
+
puts JSON.pretty_generate ActionView::Digestor.tree(CacheDigests.template_name, CacheDigests.finder).children.map(&:name)
|
12
12
|
end
|
13
13
|
|
14
14
|
class CacheDigests
|
data/lib/action_view/template.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "active_support/core_ext/object/try"
|
2
|
+
require "active_support/core_ext/kernel/singleton_class"
|
3
|
+
require "active_support/core_ext/module/delegation"
|
4
|
+
require "thread"
|
4
5
|
|
5
6
|
module ActionView
|
6
7
|
# = Action View Template
|
@@ -87,6 +88,19 @@ module ActionView
|
|
87
88
|
# expected_encoding
|
88
89
|
# )
|
89
90
|
|
91
|
+
##
|
92
|
+
# :method: local_assigns
|
93
|
+
#
|
94
|
+
# Returns a hash with the defined local variables.
|
95
|
+
#
|
96
|
+
# Given this sub template rendering:
|
97
|
+
#
|
98
|
+
# <%= render "shared/header", { headline: "Welcome", person: person } %>
|
99
|
+
#
|
100
|
+
# You can use +local_assigns+ in the sub templates to access the local variables:
|
101
|
+
#
|
102
|
+
# local_assigns[:headline] # => "Welcome"
|
103
|
+
|
90
104
|
eager_autoload do
|
91
105
|
autoload :Error
|
92
106
|
autoload :Handlers
|
@@ -103,7 +117,7 @@ module ActionView
|
|
103
117
|
|
104
118
|
# This finalizer is needed (and exactly with a proc inside another proc)
|
105
119
|
# otherwise templates leak in development.
|
106
|
-
Finalizer = proc do |method_name, mod|
|
120
|
+
Finalizer = proc do |method_name, mod| # :nodoc:
|
107
121
|
proc do
|
108
122
|
mod.module_eval do
|
109
123
|
remove_possible_method method_name
|
@@ -127,7 +141,7 @@ module ActionView
|
|
127
141
|
@compile_mutex = Mutex.new
|
128
142
|
end
|
129
143
|
|
130
|
-
# Returns
|
144
|
+
# Returns whether the underlying handler supports streaming. If so,
|
131
145
|
# a streaming buffer *may* be passed when it start rendering.
|
132
146
|
def supports_streaming?
|
133
147
|
handler.respond_to?(:supports_streaming?) && handler.supports_streaming?
|
@@ -140,7 +154,7 @@ module ActionView
|
|
140
154
|
# we use a bang in this instrumentation because you don't want to
|
141
155
|
# consume this in production. This is only slow if it's being listened to.
|
142
156
|
def render(view, locals, buffer=nil, &block)
|
143
|
-
instrument("!render_template") do
|
157
|
+
instrument("!render_template".freeze) do
|
144
158
|
compile!(view)
|
145
159
|
view.send(method_name, locals, buffer, &block)
|
146
160
|
end
|
@@ -172,7 +186,7 @@ module ActionView
|
|
172
186
|
end
|
173
187
|
|
174
188
|
def inspect
|
175
|
-
@inspect ||= defined?(Rails.root) ? identifier.sub("#{Rails.root}/", '') : identifier
|
189
|
+
@inspect ||= defined?(Rails.root) ? identifier.sub("#{Rails.root}/", ''.freeze) : identifier
|
176
190
|
end
|
177
191
|
|
178
192
|
# This method is responsible for properly setting the encoding of the
|
@@ -307,30 +321,40 @@ module ActionView
|
|
307
321
|
template = refresh(view)
|
308
322
|
template.encode!
|
309
323
|
end
|
310
|
-
raise Template::Error.new(template
|
324
|
+
raise Template::Error.new(template)
|
311
325
|
end
|
312
326
|
end
|
313
327
|
|
314
328
|
def locals_code #:nodoc:
|
329
|
+
# Only locals with valid variable names get set directly. Others will
|
330
|
+
# still be available in local_assigns.
|
331
|
+
locals = @locals - Module::RUBY_RESERVED_KEYWORDS
|
332
|
+
locals = locals.grep(/\A@?(?![A-Z0-9])(?:[[:alnum:]_]|[^\0-\177])+\z/)
|
333
|
+
|
315
334
|
# Double assign to suppress the dreaded 'assigned but unused variable' warning
|
316
|
-
|
335
|
+
locals.each_with_object("") { |key, code| code << "#{key} = #{key} = local_assigns[:#{key}];" }
|
317
336
|
end
|
318
337
|
|
319
338
|
def method_name #:nodoc:
|
320
339
|
@method_name ||= begin
|
321
340
|
m = "_#{identifier_method_name}__#{@identifier.hash}_#{__id__}"
|
322
|
-
m.tr!('-', '_')
|
341
|
+
m.tr!('-'.freeze, '_'.freeze)
|
323
342
|
m
|
324
343
|
end
|
325
344
|
end
|
326
345
|
|
327
346
|
def identifier_method_name #:nodoc:
|
328
|
-
inspect.tr('^a-z_', '_')
|
347
|
+
inspect.tr('^a-z_'.freeze, '_'.freeze)
|
329
348
|
end
|
330
349
|
|
331
350
|
def instrument(action, &block)
|
332
351
|
payload = { virtual_path: @virtual_path, identifier: @identifier }
|
333
|
-
|
352
|
+
case action
|
353
|
+
when "!render_template".freeze
|
354
|
+
ActiveSupport::Notifications.instrument("!render_template.action_view".freeze, payload, &block)
|
355
|
+
else
|
356
|
+
ActiveSupport::Notifications.instrument("#{action}.action_view".freeze, payload, &block)
|
357
|
+
end
|
334
358
|
end
|
335
359
|
end
|
336
360
|
end
|
@@ -59,13 +59,24 @@ module ActionView
|
|
59
59
|
class Error < ActionViewError #:nodoc:
|
60
60
|
SOURCE_CODE_RADIUS = 3
|
61
61
|
|
62
|
-
|
62
|
+
# Override to prevent #cause resetting during re-raise.
|
63
|
+
attr_reader :cause
|
63
64
|
|
64
|
-
def initialize(template, original_exception)
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
def initialize(template, original_exception = nil)
|
66
|
+
if original_exception
|
67
|
+
ActiveSupport::Deprecation.warn("Passing #original_exception is deprecated and has no effect. " \
|
68
|
+
"Exceptions will automatically capture the original exception.", caller)
|
69
|
+
end
|
70
|
+
|
71
|
+
super($!.message)
|
72
|
+
set_backtrace($!.backtrace)
|
73
|
+
@cause = $!
|
74
|
+
@template, @sub_templates = template, nil
|
75
|
+
end
|
76
|
+
|
77
|
+
def original_exception
|
78
|
+
ActiveSupport::Deprecation.warn("#original_exception is deprecated. Use #cause instead.", caller)
|
79
|
+
cause
|
69
80
|
end
|
70
81
|
|
71
82
|
def file_name
|
@@ -75,7 +86,7 @@ module ActionView
|
|
75
86
|
def sub_template_message
|
76
87
|
if @sub_templates
|
77
88
|
"Trace of template inclusion: " +
|
78
|
-
@sub_templates.collect
|
89
|
+
@sub_templates.collect(&:inspect).join(", ")
|
79
90
|
else
|
80
91
|
""
|
81
92
|
end
|
@@ -124,13 +135,13 @@ module ActionView
|
|
124
135
|
end
|
125
136
|
|
126
137
|
def formatted_code_for(source_code, line_counter, indent, output)
|
127
|
-
start_value = (output == :html) ? {} :
|
138
|
+
start_value = (output == :html) ? {} : []
|
128
139
|
source_code.inject(start_value) do |result, line|
|
129
140
|
line_counter += 1
|
130
141
|
if output == :html
|
131
142
|
result.update(line_counter.to_s => "%#{indent}s %s\n" % ["", line])
|
132
143
|
else
|
133
|
-
result << "%#{indent}s: %s
|
144
|
+
result << "%#{indent}s: %s" % [line_counter, line]
|
134
145
|
end
|
135
146
|
end
|
136
147
|
end
|
@@ -2,14 +2,16 @@ module ActionView #:nodoc:
|
|
2
2
|
# = Action View Template Handlers
|
3
3
|
class Template
|
4
4
|
module Handlers #:nodoc:
|
5
|
+
autoload :Raw, 'action_view/template/handlers/raw'
|
5
6
|
autoload :ERB, 'action_view/template/handlers/erb'
|
7
|
+
autoload :Html, 'action_view/template/handlers/html'
|
6
8
|
autoload :Builder, 'action_view/template/handlers/builder'
|
7
|
-
autoload :Raw, 'action_view/template/handlers/raw'
|
8
9
|
|
9
10
|
def self.extended(base)
|
10
|
-
base.register_default_template_handler :
|
11
|
+
base.register_default_template_handler :raw, Raw.new
|
12
|
+
base.register_template_handler :erb, ERB.new
|
13
|
+
base.register_template_handler :html, Html.new
|
11
14
|
base.register_template_handler :builder, Builder.new
|
12
|
-
base.register_template_handler :raw, Raw.new
|
13
15
|
base.register_template_handler :ruby, :source.to_proc
|
14
16
|
end
|
15
17
|
|
@@ -42,7 +44,7 @@ module ActionView #:nodoc:
|
|
42
44
|
end
|
43
45
|
|
44
46
|
def template_handler_extensions
|
45
|
-
@@template_handlers.keys.map
|
47
|
+
@@template_handlers.keys.map(&:to_s).sort
|
46
48
|
end
|
47
49
|
|
48
50
|
def registered_template_handler(extension)
|
@@ -1,10 +1,9 @@
|
|
1
1
|
require "pathname"
|
2
2
|
require "active_support/core_ext/class"
|
3
3
|
require "active_support/core_ext/module/attribute_accessors"
|
4
|
-
require 'active_support/core_ext/string/filters'
|
5
4
|
require "action_view/template"
|
6
5
|
require "thread"
|
7
|
-
require "
|
6
|
+
require "concurrent/map"
|
8
7
|
|
9
8
|
module ActionView
|
10
9
|
# = Action View Resolver
|
@@ -36,7 +35,7 @@ module ActionView
|
|
36
35
|
|
37
36
|
# Threadsafe template cache
|
38
37
|
class Cache #:nodoc:
|
39
|
-
class SmallCache <
|
38
|
+
class SmallCache < Concurrent::Map
|
40
39
|
def initialize(options = {})
|
41
40
|
super(options.merge(:initial_capacity => 2))
|
42
41
|
end
|
@@ -53,6 +52,11 @@ module ActionView
|
|
53
52
|
|
54
53
|
def initialize
|
55
54
|
@data = SmallCache.new(&KEY_BLOCK)
|
55
|
+
@query_cache = SmallCache.new
|
56
|
+
end
|
57
|
+
|
58
|
+
def inspect
|
59
|
+
"#<#{self.class.name}:0x#{(object_id << 1).to_s(16)} keys=#{@data.size} queries=#{@query_cache.size}>"
|
56
60
|
end
|
57
61
|
|
58
62
|
# Cache the templates returned by the block
|
@@ -71,8 +75,17 @@ module ActionView
|
|
71
75
|
end
|
72
76
|
end
|
73
77
|
|
78
|
+
def cache_query(query) # :nodoc:
|
79
|
+
if Resolver.caching?
|
80
|
+
@query_cache[query] ||= canonical_no_templates(yield)
|
81
|
+
else
|
82
|
+
yield
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
74
86
|
def clear
|
75
87
|
@data.clear
|
88
|
+
@query_cache.clear
|
76
89
|
end
|
77
90
|
|
78
91
|
private
|
@@ -113,7 +126,7 @@ module ActionView
|
|
113
126
|
# Normalizes the arguments and passes it on to find_templates.
|
114
127
|
def find_all(name, prefix=nil, partial=false, details={}, key=nil, locals=[])
|
115
128
|
cached(key, [name, prefix, partial], details, locals) do
|
116
|
-
find_templates(name, prefix, partial, details
|
129
|
+
find_templates(name, prefix, partial, details)
|
117
130
|
end
|
118
131
|
end
|
119
132
|
|
@@ -123,6 +136,10 @@ module ActionView
|
|
123
136
|
end
|
124
137
|
end
|
125
138
|
|
139
|
+
def find_all_with_query(query) # :nodoc:
|
140
|
+
@cache.cache_query(query) { find_template_paths(File.join(@path, query)) }
|
141
|
+
end
|
142
|
+
|
126
143
|
private
|
127
144
|
|
128
145
|
delegate :caching?, to: :class
|
@@ -130,8 +147,8 @@ module ActionView
|
|
130
147
|
# This is what child classes implement. No defaults are needed
|
131
148
|
# because Resolver guarantees that the arguments are present and
|
132
149
|
# normalized.
|
133
|
-
def find_templates(name, prefix, partial, details, outside_app_allowed)
|
134
|
-
raise NotImplementedError, "Subclasses must implement a find_templates(name, prefix, partial, details, outside_app_allowed) method"
|
150
|
+
def find_templates(name, prefix, partial, details, outside_app_allowed = false)
|
151
|
+
raise NotImplementedError, "Subclasses must implement a find_templates(name, prefix, partial, details, outside_app_allowed = false) method"
|
135
152
|
end
|
136
153
|
|
137
154
|
# Helpers that builds a path. Useful for building virtual paths.
|
@@ -145,7 +162,7 @@ module ActionView
|
|
145
162
|
# resolver is fresher before returning it.
|
146
163
|
def cached(key, path_info, details, locals) #:nodoc:
|
147
164
|
name, prefix, partial = path_info
|
148
|
-
locals = locals.map
|
165
|
+
locals = locals.map(&:to_s).sort!
|
149
166
|
|
150
167
|
if key
|
151
168
|
@cache.cache(key, name, prefix, partial, locals) do
|
@@ -188,10 +205,10 @@ module ActionView
|
|
188
205
|
def query(path, details, formats, outside_app_allowed)
|
189
206
|
query = build_query(path, details)
|
190
207
|
|
191
|
-
template_paths = find_template_paths
|
208
|
+
template_paths = find_template_paths(query)
|
192
209
|
template_paths = reject_files_external_to_app(template_paths) unless outside_app_allowed
|
193
210
|
|
194
|
-
template_paths.map
|
211
|
+
template_paths.map do |template|
|
195
212
|
handler, format, variant = extract_handler_and_format_and_variant(template, formats)
|
196
213
|
contents = File.binread(template)
|
197
214
|
|
@@ -201,30 +218,18 @@ module ActionView
|
|
201
218
|
:variant => variant,
|
202
219
|
:updated_at => mtime(template)
|
203
220
|
)
|
204
|
-
|
221
|
+
end
|
205
222
|
end
|
206
223
|
|
207
224
|
def reject_files_external_to_app(files)
|
208
225
|
files.reject { |filename| !inside_path?(@path, filename) }
|
209
226
|
end
|
210
227
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
!File.fnmatch(query, filename, File::FNM_EXTGLOB)
|
217
|
-
}
|
218
|
-
end
|
219
|
-
else
|
220
|
-
def find_template_paths(query)
|
221
|
-
# deals with case-insensitive file systems.
|
222
|
-
sanitizer = Hash.new { |h,dir| h[dir] = Dir["#{dir}/*"] }
|
223
|
-
|
224
|
-
Dir[query].reject { |filename|
|
225
|
-
File.directory?(filename) ||
|
226
|
-
!sanitizer[File.dirname(filename)].include?(filename)
|
227
|
-
}
|
228
|
+
def find_template_paths(query)
|
229
|
+
Dir[query].uniq.reject do |filename|
|
230
|
+
File.directory?(filename) ||
|
231
|
+
# deals with case-insensitive file systems.
|
232
|
+
!File.fnmatch(query, filename, File::FNM_EXTGLOB)
|
228
233
|
end
|
229
234
|
end
|
230
235
|
|
@@ -238,21 +243,25 @@ module ActionView
|
|
238
243
|
def build_query(path, details)
|
239
244
|
query = @pattern.dup
|
240
245
|
|
241
|
-
prefix = path.prefix.empty? ?
|
242
|
-
query.gsub!(
|
246
|
+
prefix = path.prefix.empty? ? '' : "#{escape_entry(path.prefix)}\\1"
|
247
|
+
query.gsub!(/:prefix(\/)?/, prefix)
|
243
248
|
|
244
249
|
partial = escape_entry(path.partial? ? "_#{path.name}" : path.name)
|
245
|
-
query.gsub!(
|
250
|
+
query.gsub!(/:action/, partial)
|
246
251
|
|
247
|
-
details.each do |ext,
|
248
|
-
|
252
|
+
details.each do |ext, candidates|
|
253
|
+
if ext == :variants && candidates == :any
|
254
|
+
query.gsub!(/:#{ext}/, "*")
|
255
|
+
else
|
256
|
+
query.gsub!(/:#{ext}/, "{#{candidates.compact.uniq.join(',')}}")
|
257
|
+
end
|
249
258
|
end
|
250
259
|
|
251
260
|
File.expand_path(query, @path)
|
252
261
|
end
|
253
262
|
|
254
263
|
def escape_entry(entry)
|
255
|
-
entry.gsub(/[*?{}\[\]]/, '\\\\\\&')
|
264
|
+
entry.gsub(/[*?{}\[\]]/, '\\\\\\&'.freeze)
|
256
265
|
end
|
257
266
|
|
258
267
|
# Returns the file mtime from the filesystem.
|
@@ -264,16 +273,10 @@ module ActionView
|
|
264
273
|
# from the path, or the handler, we should return the array of formats given
|
265
274
|
# to the resolver.
|
266
275
|
def extract_handler_and_format_and_variant(path, default_formats)
|
267
|
-
pieces = File.basename(path).split(
|
276
|
+
pieces = File.basename(path).split('.'.freeze)
|
268
277
|
pieces.shift
|
269
278
|
|
270
279
|
extension = pieces.pop
|
271
|
-
unless extension
|
272
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
273
|
-
The file #{path} did not specify a template handler. The default is
|
274
|
-
currently ERB, but will change to RAW in the future.
|
275
|
-
MSG
|
276
|
-
end
|
277
280
|
|
278
281
|
handler = Template.handler_for_extension(extension)
|
279
282
|
format, variant = pieces.last.split(EXTENSIONS[:variants], 2) if pieces.last
|
@@ -306,7 +309,7 @@ module ActionView
|
|
306
309
|
#
|
307
310
|
# ActionController::Base.view_paths = FileSystemResolver.new(
|
308
311
|
# Rails.root.join("app/views"),
|
309
|
-
# ":prefix{
|
312
|
+
# ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}",
|
310
313
|
# )
|
311
314
|
#
|
312
315
|
# ==== Pattern format and variables
|
@@ -345,7 +348,11 @@ module ActionView
|
|
345
348
|
query = escape_entry(File.join(@path, path))
|
346
349
|
|
347
350
|
exts = EXTENSIONS.map do |ext, prefix|
|
348
|
-
|
351
|
+
if ext == :variants && details[ext] == :any
|
352
|
+
"{#{prefix}*,}"
|
353
|
+
else
|
354
|
+
"{#{details[ext].compact.uniq.map { |e| "#{prefix}#{e}," }.join}}"
|
355
|
+
end
|
349
356
|
end.join
|
350
357
|
|
351
358
|
query + exts
|
@@ -1,23 +1,15 @@
|
|
1
|
-
require 'set'
|
2
1
|
require 'active_support/core_ext/module/attribute_accessors'
|
3
2
|
|
4
3
|
module ActionView
|
5
4
|
class Template
|
6
5
|
class Types
|
7
6
|
class Type
|
8
|
-
|
9
|
-
self.types = Set.new
|
10
|
-
|
11
|
-
def self.register(*t)
|
12
|
-
types.merge(t.map { |type| type.to_s })
|
13
|
-
end
|
14
|
-
|
15
|
-
register :html, :text, :js, :css, :xml, :json
|
7
|
+
SET = Struct.new(:symbols).new([ :html, :text, :js, :css, :xml, :json ])
|
16
8
|
|
17
9
|
def self.[](type)
|
18
|
-
|
19
|
-
|
20
|
-
|
10
|
+
if type.is_a?(self)
|
11
|
+
type
|
12
|
+
else
|
21
13
|
new(type)
|
22
14
|
end
|
23
15
|
end
|
@@ -28,16 +20,18 @@ module ActionView
|
|
28
20
|
@symbol = symbol.to_sym
|
29
21
|
end
|
30
22
|
|
31
|
-
|
23
|
+
def to_s
|
24
|
+
@symbol.to_s
|
25
|
+
end
|
32
26
|
alias to_str to_s
|
33
27
|
|
34
28
|
def ref
|
35
|
-
|
29
|
+
@symbol
|
36
30
|
end
|
31
|
+
alias to_sym ref
|
37
32
|
|
38
33
|
def ==(type)
|
39
|
-
|
40
|
-
symbol.to_sym == type.to_sym
|
34
|
+
@symbol == type.to_sym unless type.blank?
|
41
35
|
end
|
42
36
|
end
|
43
37
|
|
@@ -52,6 +46,10 @@ module ActionView
|
|
52
46
|
def self.[](type)
|
53
47
|
type_klass[type]
|
54
48
|
end
|
49
|
+
|
50
|
+
def self.symbols
|
51
|
+
type_klass::SET.symbols
|
52
|
+
end
|
55
53
|
end
|
56
54
|
end
|
57
55
|
end
|