actionview 4.2.11.1 → 6.0.4
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 +4 -4
- data/CHANGELOG.md +201 -192
- data/MIT-LICENSE +1 -1
- data/README.rdoc +9 -8
- data/lib/action_view/base.rb +144 -37
- data/lib/action_view/buffers.rb +18 -1
- data/lib/action_view/cache_expiry.rb +53 -0
- data/lib/action_view/context.rb +8 -12
- data/lib/action_view/dependency_tracker.rb +54 -20
- data/lib/action_view/digestor.rb +88 -85
- data/lib/action_view/flows.rb +11 -12
- data/lib/action_view/gem_version.rb +6 -4
- data/lib/action_view/helpers/active_model_helper.rb +16 -11
- data/lib/action_view/helpers/asset_tag_helper.rb +241 -82
- data/lib/action_view/helpers/asset_url_helper.rb +171 -67
- data/lib/action_view/helpers/atom_feed_helper.rb +19 -17
- data/lib/action_view/helpers/cache_helper.rb +112 -42
- data/lib/action_view/helpers/capture_helper.rb +20 -13
- data/lib/action_view/helpers/controller_helper.rb +15 -4
- data/lib/action_view/helpers/csp_helper.rb +26 -0
- data/lib/action_view/helpers/csrf_helper.rb +8 -6
- data/lib/action_view/helpers/date_helper.rb +230 -129
- data/lib/action_view/helpers/debug_helper.rb +7 -6
- data/lib/action_view/helpers/form_helper.rb +755 -129
- data/lib/action_view/helpers/form_options_helper.rb +130 -75
- data/lib/action_view/helpers/form_tag_helper.rb +116 -71
- data/lib/action_view/helpers/javascript_helper.rb +30 -14
- data/lib/action_view/helpers/number_helper.rb +84 -59
- data/lib/action_view/helpers/output_safety_helper.rb +36 -4
- data/lib/action_view/helpers/rendering_helper.rb +11 -8
- data/lib/action_view/helpers/sanitize_helper.rb +30 -31
- data/lib/action_view/helpers/tag_helper.rb +201 -75
- data/lib/action_view/helpers/tags/base.rb +138 -98
- data/lib/action_view/helpers/tags/check_box.rb +20 -19
- data/lib/action_view/helpers/tags/checkable.rb +4 -2
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +12 -34
- data/lib/action_view/helpers/tags/collection_helpers.rb +69 -36
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +6 -12
- data/lib/action_view/helpers/tags/collection_select.rb +4 -2
- data/lib/action_view/helpers/tags/color_field.rb +4 -3
- data/lib/action_view/helpers/tags/date_field.rb +2 -1
- data/lib/action_view/helpers/tags/date_select.rb +37 -36
- data/lib/action_view/helpers/tags/datetime_field.rb +4 -3
- data/lib/action_view/helpers/tags/datetime_local_field.rb +2 -1
- data/lib/action_view/helpers/tags/datetime_select.rb +2 -0
- data/lib/action_view/helpers/tags/email_field.rb +2 -0
- data/lib/action_view/helpers/tags/file_field.rb +2 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +4 -2
- data/lib/action_view/helpers/tags/hidden_field.rb +2 -0
- data/lib/action_view/helpers/tags/label.rb +3 -2
- data/lib/action_view/helpers/tags/month_field.rb +2 -1
- data/lib/action_view/helpers/tags/number_field.rb +2 -0
- data/lib/action_view/helpers/tags/password_field.rb +3 -1
- data/lib/action_view/helpers/tags/placeholderable.rb +3 -1
- data/lib/action_view/helpers/tags/radio_button.rb +7 -6
- data/lib/action_view/helpers/tags/range_field.rb +2 -0
- data/lib/action_view/helpers/tags/search_field.rb +14 -9
- data/lib/action_view/helpers/tags/select.rb +11 -10
- data/lib/action_view/helpers/tags/tel_field.rb +2 -0
- data/lib/action_view/helpers/tags/text_area.rb +4 -2
- data/lib/action_view/helpers/tags/text_field.rb +8 -8
- data/lib/action_view/helpers/tags/time_field.rb +2 -1
- data/lib/action_view/helpers/tags/time_select.rb +2 -0
- data/lib/action_view/helpers/tags/time_zone_select.rb +3 -1
- data/lib/action_view/helpers/tags/translator.rb +15 -16
- data/lib/action_view/helpers/tags/url_field.rb +2 -0
- data/lib/action_view/helpers/tags/week_field.rb +2 -1
- data/lib/action_view/helpers/tags.rb +3 -1
- data/lib/action_view/helpers/text_helper.rb +56 -38
- data/lib/action_view/helpers/translation_helper.rb +91 -47
- data/lib/action_view/helpers/url_helper.rb +160 -105
- data/lib/action_view/helpers.rb +5 -3
- data/lib/action_view/layouts.rb +65 -61
- data/lib/action_view/log_subscriber.rb +61 -10
- data/lib/action_view/lookup_context.rb +147 -89
- data/lib/action_view/model_naming.rb +3 -1
- data/lib/action_view/path_set.rb +28 -23
- data/lib/action_view/railtie.rb +62 -6
- data/lib/action_view/record_identifier.rb +53 -26
- data/lib/action_view/renderer/abstract_renderer.rb +71 -13
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +103 -0
- data/lib/action_view/renderer/partial_renderer.rb +239 -225
- data/lib/action_view/renderer/renderer.rb +22 -8
- data/lib/action_view/renderer/streaming_template_renderer.rb +54 -54
- data/lib/action_view/renderer/template_renderer.rb +79 -73
- data/lib/action_view/rendering.rb +68 -44
- data/lib/action_view/routing_url_for.rb +33 -22
- data/lib/action_view/tasks/cache_digests.rake +25 -0
- data/lib/action_view/template/error.rb +44 -29
- data/lib/action_view/template/handlers/builder.rb +12 -13
- data/lib/action_view/template/handlers/erb/erubi.rb +87 -0
- data/lib/action_view/template/handlers/erb.rb +24 -86
- data/lib/action_view/template/handlers/html.rb +11 -0
- data/lib/action_view/template/handlers/raw.rb +4 -4
- data/lib/action_view/template/handlers.rb +38 -8
- data/lib/action_view/template/html.rb +19 -10
- data/lib/action_view/template/inline.rb +22 -0
- data/lib/action_view/template/raw_file.rb +28 -0
- data/lib/action_view/template/resolver.rb +217 -193
- data/lib/action_view/template/sources/file.rb +17 -0
- data/lib/action_view/template/sources.rb +13 -0
- data/lib/action_view/template/text.rb +11 -10
- data/lib/action_view/template/types.rb +18 -18
- data/lib/action_view/template.rb +146 -90
- data/lib/action_view/test_case.rb +52 -32
- data/lib/action_view/testing/resolvers.rb +46 -34
- data/lib/action_view/unbound_template.rb +31 -0
- data/lib/action_view/version.rb +3 -1
- data/lib/action_view/view_paths.rb +48 -31
- data/lib/action_view.rb +11 -8
- data/lib/assets/compiled/rails-ujs.js +746 -0
- metadata +38 -29
- data/lib/action_view/helpers/record_tag_helper.rb +0 -108
- data/lib/action_view/tasks/dependencies.rake +0 -23
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :cache_digests do
|
4
|
+
desc "Lookup nested dependencies for TEMPLATE (like messages/show or comments/_comment.html)"
|
5
|
+
task nested_dependencies: :environment do
|
6
|
+
abort "You must provide TEMPLATE for the task to run" unless ENV["TEMPLATE"].present?
|
7
|
+
puts JSON.pretty_generate ActionView::Digestor.tree(CacheDigests.template_name, CacheDigests.finder).children.map(&:to_dep_map)
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Lookup first-level dependencies for TEMPLATE (like messages/show or comments/_comment.html)"
|
11
|
+
task dependencies: :environment do
|
12
|
+
abort "You must provide TEMPLATE for the task to run" unless ENV["TEMPLATE"].present?
|
13
|
+
puts JSON.pretty_generate ActionView::Digestor.tree(CacheDigests.template_name, CacheDigests.finder).children.map(&:name)
|
14
|
+
end
|
15
|
+
|
16
|
+
class CacheDigests
|
17
|
+
def self.template_name
|
18
|
+
ENV["TEMPLATE"].split(".", 2).first
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.finder
|
22
|
+
ApplicationController.new.lookup_context
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/enumerable"
|
2
4
|
|
3
5
|
module ActionView
|
@@ -8,9 +10,6 @@ module ActionView
|
|
8
10
|
class EncodingError < StandardError #:nodoc:
|
9
11
|
end
|
10
12
|
|
11
|
-
class MissingRequestError < StandardError #:nodoc:
|
12
|
-
end
|
13
|
-
|
14
13
|
class WrongEncodingError < EncodingError #:nodoc:
|
15
14
|
def initialize(string, encoding)
|
16
15
|
@string, @encoding = string, encoding
|
@@ -35,10 +34,10 @@ module ActionView
|
|
35
34
|
prefixes = Array(prefixes)
|
36
35
|
template_type = if partial
|
37
36
|
"partial"
|
38
|
-
elsif
|
39
|
-
|
37
|
+
elsif /layouts/i.match?(path)
|
38
|
+
"layout"
|
40
39
|
else
|
41
|
-
|
40
|
+
"template"
|
42
41
|
end
|
43
42
|
|
44
43
|
if partial && path.present?
|
@@ -59,13 +58,14 @@ module ActionView
|
|
59
58
|
class Error < ActionViewError #:nodoc:
|
60
59
|
SOURCE_CODE_RADIUS = 3
|
61
60
|
|
62
|
-
|
61
|
+
# Override to prevent #cause resetting during re-raise.
|
62
|
+
attr_reader :cause
|
63
63
|
|
64
|
-
def initialize(template
|
65
|
-
super(
|
66
|
-
|
67
|
-
@
|
68
|
-
|
64
|
+
def initialize(template)
|
65
|
+
super($!.message)
|
66
|
+
set_backtrace($!.backtrace)
|
67
|
+
@cause = $!
|
68
|
+
@template, @sub_templates = template, nil
|
69
69
|
end
|
70
70
|
|
71
71
|
def file_name
|
@@ -75,25 +75,25 @@ module ActionView
|
|
75
75
|
def sub_template_message
|
76
76
|
if @sub_templates
|
77
77
|
"Trace of template inclusion: " +
|
78
|
-
@sub_templates.collect
|
78
|
+
@sub_templates.collect(&:inspect).join(", ")
|
79
79
|
else
|
80
80
|
""
|
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)
|
@@ -109,33 +109,48 @@ module ActionView
|
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
-
def
|
112
|
+
def annotated_source_code
|
113
113
|
source_extract(4)
|
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 "
|
121
120
|
else
|
122
|
-
|
121
|
+
"in "
|
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\n" % [line_counter, line]
|
134
|
-
end
|
129
|
+
indent_template % [line_counter, line]
|
135
130
|
end
|
136
131
|
end
|
137
132
|
end
|
138
133
|
end
|
139
134
|
|
140
135
|
TemplateError = Template::Error
|
136
|
+
|
137
|
+
class SyntaxErrorInTemplate < TemplateError #:nodoc
|
138
|
+
def initialize(template, offending_code_string)
|
139
|
+
@offending_code_string = offending_code_string
|
140
|
+
super(template)
|
141
|
+
end
|
142
|
+
|
143
|
+
def message
|
144
|
+
<<~MESSAGE
|
145
|
+
Encountered a syntax error while rendering template: check #{@offending_code_string}
|
146
|
+
MESSAGE
|
147
|
+
end
|
148
|
+
|
149
|
+
def annotated_source_code
|
150
|
+
@offending_code_string.split("\n").map.with_index(1) { |line, index|
|
151
|
+
indentation = " " * 4
|
152
|
+
"#{index}:#{indentation}#{line}"
|
153
|
+
}
|
154
|
+
end
|
155
|
+
end
|
141
156
|
end
|
@@ -1,26 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionView
|
2
4
|
module Template::Handlers
|
3
5
|
class Builder
|
4
|
-
|
5
|
-
class_attribute :default_format
|
6
|
-
self.default_format = :xml
|
6
|
+
class_attribute :default_format, default: :xml
|
7
7
|
|
8
|
-
def call(template)
|
8
|
+
def call(template, source)
|
9
9
|
require_engine
|
10
|
-
"xml = ::Builder::XmlMarkup.new(:indent => 2);"
|
10
|
+
"xml = ::Builder::XmlMarkup.new(:indent => 2);" \
|
11
11
|
"self.output_buffer = xml.target!;" +
|
12
|
-
|
12
|
+
source +
|
13
13
|
";xml.target!;"
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
private
|
17
|
+
def require_engine # :doc:
|
18
|
+
@required ||= begin
|
19
|
+
require "builder"
|
20
|
+
true
|
21
|
+
end
|
22
22
|
end
|
23
|
-
end
|
24
23
|
end
|
25
24
|
end
|
26
25
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "erubi"
|
4
|
+
|
5
|
+
module ActionView
|
6
|
+
class Template
|
7
|
+
module Handlers
|
8
|
+
class ERB
|
9
|
+
class Erubi < ::Erubi::Engine
|
10
|
+
# :nodoc: all
|
11
|
+
def initialize(input, properties = {})
|
12
|
+
@newline_pending = 0
|
13
|
+
|
14
|
+
# Dup properties so that we don't modify argument
|
15
|
+
properties = Hash[properties]
|
16
|
+
properties[:preamble] = ""
|
17
|
+
properties[:postamble] = "@output_buffer.to_s"
|
18
|
+
properties[:bufvar] = "@output_buffer"
|
19
|
+
properties[:escapefunc] = ""
|
20
|
+
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def evaluate(action_view_erb_handler_context)
|
25
|
+
src = @src
|
26
|
+
view = Class.new(ActionView::Base) {
|
27
|
+
include action_view_erb_handler_context._routes.url_helpers
|
28
|
+
class_eval("define_method(:_template) { |local_assigns, output_buffer| #{src} }", defined?(@filename) ? @filename : "(erubi)", 0)
|
29
|
+
}.empty
|
30
|
+
view._run(:_template, nil, {}, ActionView::OutputBuffer.new)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def add_text(text)
|
35
|
+
return if text.empty?
|
36
|
+
|
37
|
+
if text == "\n"
|
38
|
+
@newline_pending += 1
|
39
|
+
else
|
40
|
+
src << "@output_buffer.safe_append='"
|
41
|
+
src << "\n" * @newline_pending if @newline_pending > 0
|
42
|
+
src << text.gsub(/['\\]/, '\\\\\&')
|
43
|
+
src << "'.freeze;"
|
44
|
+
|
45
|
+
@newline_pending = 0
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
BLOCK_EXPR = /\s*((\s+|\))do|\{)(\s*\|[^|]*\|)?\s*\Z/
|
50
|
+
|
51
|
+
def add_expression(indicator, code)
|
52
|
+
flush_newline_if_pending(src)
|
53
|
+
|
54
|
+
if (indicator == "==") || @escape
|
55
|
+
src << "@output_buffer.safe_expr_append="
|
56
|
+
else
|
57
|
+
src << "@output_buffer.append="
|
58
|
+
end
|
59
|
+
|
60
|
+
if BLOCK_EXPR.match?(code)
|
61
|
+
src << " " << code
|
62
|
+
else
|
63
|
+
src << "(" << code << ");"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def add_code(code)
|
68
|
+
flush_newline_if_pending(src)
|
69
|
+
super
|
70
|
+
end
|
71
|
+
|
72
|
+
def add_postamble(_)
|
73
|
+
flush_newline_if_pending(src)
|
74
|
+
super
|
75
|
+
end
|
76
|
+
|
77
|
+
def flush_newline_if_pending(src)
|
78
|
+
if @newline_pending > 0
|
79
|
+
src << "@output_buffer.safe_append='#{"\n" * @newline_pending}'.freeze;"
|
80
|
+
@newline_pending = 0
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -1,96 +1,35 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionView
|
4
4
|
class Template
|
5
5
|
module Handlers
|
6
|
-
class Erubis < ::Erubis::Eruby
|
7
|
-
def add_preamble(src)
|
8
|
-
@newline_pending = 0
|
9
|
-
src << "@output_buffer = output_buffer || ActionView::OutputBuffer.new;"
|
10
|
-
end
|
11
|
-
|
12
|
-
def add_text(src, text)
|
13
|
-
return if text.empty?
|
14
|
-
|
15
|
-
if text == "\n"
|
16
|
-
@newline_pending += 1
|
17
|
-
else
|
18
|
-
src << "@output_buffer.safe_append='"
|
19
|
-
src << "\n" * @newline_pending if @newline_pending > 0
|
20
|
-
src << escape_text(text)
|
21
|
-
src << "'.freeze;"
|
22
|
-
|
23
|
-
@newline_pending = 0
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
# Erubis toggles <%= and <%== behavior when escaping is enabled.
|
28
|
-
# We override to always treat <%== as escaped.
|
29
|
-
def add_expr(src, code, indicator)
|
30
|
-
case indicator
|
31
|
-
when '=='
|
32
|
-
add_expr_escaped(src, code)
|
33
|
-
else
|
34
|
-
super
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
BLOCK_EXPR = /\s*((\s+|\))do|\{)(\s*\|[^|]*\|)?\s*\Z/
|
39
|
-
|
40
|
-
def add_expr_literal(src, code)
|
41
|
-
flush_newline_if_pending(src)
|
42
|
-
if code =~ BLOCK_EXPR
|
43
|
-
src << '@output_buffer.append= ' << code
|
44
|
-
else
|
45
|
-
src << '@output_buffer.append=(' << code << ');'
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def add_expr_escaped(src, code)
|
50
|
-
flush_newline_if_pending(src)
|
51
|
-
if code =~ BLOCK_EXPR
|
52
|
-
src << "@output_buffer.safe_expr_append= " << code
|
53
|
-
else
|
54
|
-
src << "@output_buffer.safe_expr_append=(" << code << ");"
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def add_stmt(src, code)
|
59
|
-
flush_newline_if_pending(src)
|
60
|
-
super
|
61
|
-
end
|
62
|
-
|
63
|
-
def add_postamble(src)
|
64
|
-
flush_newline_if_pending(src)
|
65
|
-
src << '@output_buffer.to_s'
|
66
|
-
end
|
67
|
-
|
68
|
-
def flush_newline_if_pending(src)
|
69
|
-
if @newline_pending > 0
|
70
|
-
src << "@output_buffer.safe_append='#{"\n" * @newline_pending}'.freeze;"
|
71
|
-
@newline_pending = 0
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
6
|
class ERB
|
7
|
+
autoload :Erubi, "action_view/template/handlers/erb/erubi"
|
8
|
+
|
77
9
|
# Specify trim mode for the ERB compiler. Defaults to '-'.
|
78
10
|
# See ERB documentation for suitable values.
|
79
|
-
class_attribute :erb_trim_mode
|
80
|
-
self.erb_trim_mode = '-'
|
11
|
+
class_attribute :erb_trim_mode, default: "-"
|
81
12
|
|
82
13
|
# Default implementation used.
|
83
|
-
class_attribute :erb_implementation
|
84
|
-
self.erb_implementation = Erubis
|
14
|
+
class_attribute :erb_implementation, default: Erubi
|
85
15
|
|
86
16
|
# Do not escape templates of these mime types.
|
87
|
-
class_attribute :
|
88
|
-
|
17
|
+
class_attribute :escape_ignore_list, default: ["text/plain"]
|
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
|
89
28
|
|
90
29
|
ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")
|
91
30
|
|
92
|
-
def self.call(template)
|
93
|
-
new.call(template)
|
31
|
+
def self.call(template, source)
|
32
|
+
new.call(template, source)
|
94
33
|
end
|
95
34
|
|
96
35
|
def supports_streaming?
|
@@ -101,30 +40,29 @@ module ActionView
|
|
101
40
|
true
|
102
41
|
end
|
103
42
|
|
104
|
-
def call(template)
|
43
|
+
def call(template, source)
|
105
44
|
# First, convert to BINARY, so in case the encoding is
|
106
45
|
# wrong, we can still find an encoding tag
|
107
46
|
# (<%# encoding %>) inside the String using a regular
|
108
47
|
# expression
|
109
|
-
template_source =
|
48
|
+
template_source = source.dup.force_encoding(Encoding::ASCII_8BIT)
|
110
49
|
|
111
|
-
erb = template_source.gsub(ENCODING_TAG,
|
50
|
+
erb = template_source.gsub(ENCODING_TAG, "")
|
112
51
|
encoding = $2
|
113
52
|
|
114
|
-
erb.force_encoding valid_encoding(
|
53
|
+
erb.force_encoding valid_encoding(source.dup, encoding)
|
115
54
|
|
116
55
|
# Always make sure we return a String in the default_internal
|
117
56
|
erb.encode!
|
118
57
|
|
119
58
|
self.class.erb_implementation.new(
|
120
59
|
erb,
|
121
|
-
:
|
122
|
-
:
|
60
|
+
escape: (self.class.escape_ignore_list.include? template.type),
|
61
|
+
trim: (self.class.erb_trim_mode == "-")
|
123
62
|
).src
|
124
63
|
end
|
125
64
|
|
126
65
|
private
|
127
|
-
|
128
66
|
def valid_encoding(string, encoding)
|
129
67
|
# If a magic encoding comment was found, tag the
|
130
68
|
# String with this encoding. This is for a case
|
@@ -1,10 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionView
|
2
4
|
module Template::Handlers
|
3
5
|
class Raw
|
4
|
-
def call(template)
|
5
|
-
|
6
|
-
|
7
|
-
'%q:' + escaped + ':;'
|
6
|
+
def call(template, source)
|
7
|
+
"#{source.inspect}.html_safe;"
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
@@ -1,16 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/deprecation"
|
4
|
+
|
1
5
|
module ActionView #:nodoc:
|
2
6
|
# = Action View Template Handlers
|
3
|
-
class Template
|
7
|
+
class Template #:nodoc:
|
4
8
|
module Handlers #:nodoc:
|
5
|
-
autoload :
|
6
|
-
autoload :
|
7
|
-
autoload :
|
9
|
+
autoload :Raw, "action_view/template/handlers/raw"
|
10
|
+
autoload :ERB, "action_view/template/handlers/erb"
|
11
|
+
autoload :Html, "action_view/template/handlers/html"
|
12
|
+
autoload :Builder, "action_view/template/handlers/builder"
|
8
13
|
|
9
14
|
def self.extended(base)
|
10
|
-
base.register_default_template_handler :
|
15
|
+
base.register_default_template_handler :raw, Raw.new
|
16
|
+
base.register_template_handler :erb, ERB.new
|
17
|
+
base.register_template_handler :html, Html.new
|
11
18
|
base.register_template_handler :builder, Builder.new
|
12
|
-
base.register_template_handler :
|
13
|
-
base.register_template_handler :ruby, :source.to_proc
|
19
|
+
base.register_template_handler :ruby, lambda { |_, source| source }
|
14
20
|
end
|
15
21
|
|
16
22
|
@@template_handlers = {}
|
@@ -20,11 +26,35 @@ module ActionView #:nodoc:
|
|
20
26
|
@@template_extensions ||= @@template_handlers.keys
|
21
27
|
end
|
22
28
|
|
29
|
+
class LegacyHandlerWrapper < SimpleDelegator # :nodoc:
|
30
|
+
def call(view, source)
|
31
|
+
__getobj__.call(ActionView::Template::LegacyTemplate.new(view, source))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
23
35
|
# Register an object that knows how to handle template files with the given
|
24
36
|
# extensions. This can be used to implement new template types.
|
25
37
|
# The handler must respond to +:call+, which will be passed the template
|
26
38
|
# and should return the rendered template as a String.
|
27
39
|
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
|
+
|
28
58
|
raise(ArgumentError, "Extension is required") if extensions.empty?
|
29
59
|
extensions.each do |extension|
|
30
60
|
@@template_handlers[extension.to_sym] = handler
|
@@ -42,7 +72,7 @@ module ActionView #:nodoc:
|
|
42
72
|
end
|
43
73
|
|
44
74
|
def template_handler_extensions
|
45
|
-
@@template_handlers.keys.map
|
75
|
+
@@template_handlers.keys.map(&:to_s).sort
|
46
76
|
end
|
47
77
|
|
48
78
|
def registered_template_handler(extension)
|
@@ -1,22 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/deprecation"
|
4
|
+
|
1
5
|
module ActionView #:nodoc:
|
2
6
|
# = Action View HTML Template
|
3
|
-
class Template
|
7
|
+
class Template #:nodoc:
|
4
8
|
class HTML #:nodoc:
|
5
|
-
|
9
|
+
attr_reader :type
|
6
10
|
|
7
11
|
def initialize(string, type = nil)
|
12
|
+
unless type
|
13
|
+
ActiveSupport::Deprecation.warn "ActionView::Template::HTML#initialize requires a type parameter"
|
14
|
+
type = :html
|
15
|
+
end
|
16
|
+
|
8
17
|
@string = string.to_s
|
9
|
-
@type =
|
10
|
-
@type ||= Types[:html]
|
18
|
+
@type = type
|
11
19
|
end
|
12
20
|
|
13
21
|
def identifier
|
14
|
-
|
22
|
+
"html template"
|
15
23
|
end
|
16
24
|
|
17
|
-
|
18
|
-
'html template'
|
19
|
-
end
|
25
|
+
alias_method :inspect, :identifier
|
20
26
|
|
21
27
|
def to_str
|
22
28
|
ERB::Util.h(@string)
|
@@ -26,9 +32,12 @@ module ActionView #:nodoc:
|
|
26
32
|
to_str
|
27
33
|
end
|
28
34
|
|
29
|
-
def
|
30
|
-
|
35
|
+
def format
|
36
|
+
@type
|
31
37
|
end
|
38
|
+
|
39
|
+
def formats; Array(format); end
|
40
|
+
deprecate :formats
|
32
41
|
end
|
33
42
|
end
|
34
43
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionView #:nodoc:
|
4
|
+
class Template #:nodoc:
|
5
|
+
class Inline < Template #:nodoc:
|
6
|
+
# This finalizer is needed (and exactly with a proc inside another proc)
|
7
|
+
# otherwise templates leak in development.
|
8
|
+
Finalizer = proc do |method_name, mod| # :nodoc:
|
9
|
+
proc do
|
10
|
+
mod.module_eval do
|
11
|
+
remove_possible_method method_name
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def compile(mod)
|
17
|
+
super
|
18
|
+
ObjectSpace.define_finalizer(self, Finalizer[method_name, mod])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionView #:nodoc:
|
4
|
+
# = Action View RawFile Template
|
5
|
+
class Template #:nodoc:
|
6
|
+
class RawFile #:nodoc:
|
7
|
+
attr_accessor :type, :format
|
8
|
+
|
9
|
+
def initialize(filename)
|
10
|
+
@filename = filename.to_s
|
11
|
+
extname = ::File.extname(filename).delete(".")
|
12
|
+
@type = Template::Types[extname] || Template::Types[:text]
|
13
|
+
@format = @type.symbol
|
14
|
+
end
|
15
|
+
|
16
|
+
def identifier
|
17
|
+
@filename
|
18
|
+
end
|
19
|
+
|
20
|
+
def render(*args)
|
21
|
+
::File.read(@filename)
|
22
|
+
end
|
23
|
+
|
24
|
+
def formats; Array(format); end
|
25
|
+
deprecate :formats
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|