actionview 7.0.1 → 7.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +281 -202
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -3
- data/app/assets/javascripts/rails-ujs.esm.js +693 -0
- data/app/assets/javascripts/rails-ujs.js +630 -0
- data/lib/action_view/base.rb +33 -12
- data/lib/action_view/buffers.rb +106 -8
- data/lib/action_view/cache_expiry.rb +40 -43
- data/lib/action_view/context.rb +1 -1
- data/lib/action_view/deprecator.rb +7 -0
- data/lib/action_view/digestor.rb +1 -1
- data/lib/action_view/gem_version.rb +2 -2
- data/lib/action_view/helpers/active_model_helper.rb +1 -1
- data/lib/action_view/helpers/asset_tag_helper.rb +133 -48
- data/lib/action_view/helpers/asset_url_helper.rb +13 -12
- data/lib/action_view/helpers/atom_feed_helper.rb +5 -5
- data/lib/action_view/helpers/cache_helper.rb +3 -9
- data/lib/action_view/helpers/capture_helper.rb +26 -12
- data/lib/action_view/helpers/content_exfiltration_prevention_helper.rb +70 -0
- data/lib/action_view/helpers/controller_helper.rb +6 -0
- data/lib/action_view/helpers/csp_helper.rb +2 -2
- data/lib/action_view/helpers/csrf_helper.rb +3 -3
- data/lib/action_view/helpers/date_helper.rb +76 -64
- data/lib/action_view/helpers/debug_helper.rb +3 -3
- data/lib/action_view/helpers/form_helper.rb +62 -31
- data/lib/action_view/helpers/form_options_helper.rb +6 -3
- data/lib/action_view/helpers/form_tag_helper.rb +88 -44
- data/lib/action_view/helpers/javascript_helper.rb +1 -0
- data/lib/action_view/helpers/number_helper.rb +15 -13
- 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 +34 -15
- data/lib/action_view/helpers/tag_helper.rb +27 -16
- data/lib/action_view/helpers/tags/base.rb +11 -52
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +1 -0
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +1 -0
- data/lib/action_view/helpers/tags/collection_select.rb +3 -0
- data/lib/action_view/helpers/tags/date_field.rb +1 -1
- data/lib/action_view/helpers/tags/date_select.rb +2 -0
- data/lib/action_view/helpers/tags/datetime_field.rb +14 -6
- data/lib/action_view/helpers/tags/datetime_local_field.rb +11 -2
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +3 -0
- data/lib/action_view/helpers/tags/month_field.rb +1 -1
- data/lib/action_view/helpers/tags/select.rb +4 -1
- data/lib/action_view/helpers/tags/select_renderer.rb +56 -0
- data/lib/action_view/helpers/tags/time_field.rb +1 -1
- data/lib/action_view/helpers/tags/time_zone_select.rb +3 -0
- data/lib/action_view/helpers/tags/week_field.rb +1 -1
- data/lib/action_view/helpers/tags/weekday_select.rb +3 -0
- data/lib/action_view/helpers/tags.rb +2 -0
- data/lib/action_view/helpers/text_helper.rb +33 -17
- data/lib/action_view/helpers/translation_helper.rb +6 -6
- data/lib/action_view/helpers/url_helper.rb +90 -65
- data/lib/action_view/helpers.rb +2 -0
- data/lib/action_view/layouts.rb +13 -8
- data/lib/action_view/log_subscriber.rb +49 -32
- data/lib/action_view/lookup_context.rb +29 -13
- data/lib/action_view/path_registry.rb +57 -0
- data/lib/action_view/path_set.rb +13 -14
- data/lib/action_view/railtie.rb +26 -3
- data/lib/action_view/record_identifier.rb +16 -9
- data/lib/action_view/renderer/abstract_renderer.rb +1 -1
- data/lib/action_view/renderer/collection_renderer.rb +9 -1
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +21 -3
- data/lib/action_view/renderer/partial_renderer.rb +3 -2
- data/lib/action_view/renderer/renderer.rb +2 -0
- data/lib/action_view/renderer/streaming_template_renderer.rb +3 -2
- data/lib/action_view/renderer/template_renderer.rb +3 -2
- data/lib/action_view/rendering.rb +24 -6
- data/lib/action_view/ripper_ast_parser.rb +6 -6
- data/lib/action_view/routing_url_for.rb +7 -4
- data/lib/action_view/template/error.rb +14 -1
- data/lib/action_view/template/handlers/builder.rb +4 -4
- data/lib/action_view/template/handlers/erb/erubi.rb +23 -27
- data/lib/action_view/template/handlers/erb.rb +73 -1
- data/lib/action_view/template/handlers.rb +1 -1
- data/lib/action_view/template/html.rb +1 -1
- data/lib/action_view/template/raw_file.rb +1 -1
- data/lib/action_view/template/renderable.rb +1 -1
- data/lib/action_view/template/resolver.rb +15 -5
- data/lib/action_view/template/text.rb +1 -1
- data/lib/action_view/template/types.rb +25 -34
- data/lib/action_view/template.rb +227 -53
- data/lib/action_view/template_path.rb +2 -0
- data/lib/action_view/test_case.rb +174 -21
- data/lib/action_view/unbound_template.rb +15 -5
- data/lib/action_view/version.rb +1 -1
- data/lib/action_view/view_paths.rb +19 -28
- data/lib/action_view.rb +4 -1
- data/lib/assets/compiled/rails-ujs.js +36 -5
- metadata +27 -27
@@ -9,6 +9,9 @@ require "rails-dom-testing"
|
|
9
9
|
|
10
10
|
module ActionView
|
11
11
|
# = Action View Test Case
|
12
|
+
#
|
13
|
+
# Read more about <tt>ActionView::TestCase</tt> in {Testing Rails Applications}[https://guides.rubyonrails.org/testing.html#testing-view-partials]
|
14
|
+
# in the guides.
|
12
15
|
class TestCase < ActiveSupport::TestCase
|
13
16
|
class TestController < ActionController::Base
|
14
17
|
include ActionDispatch::TestProcess
|
@@ -57,9 +60,96 @@ module ActionView
|
|
57
60
|
include ActiveSupport::Testing::ConstantLookup
|
58
61
|
|
59
62
|
delegate :lookup_context, to: :controller
|
60
|
-
attr_accessor :controller, :
|
63
|
+
attr_accessor :controller, :request, :output_buffer
|
61
64
|
|
62
65
|
module ClassMethods
|
66
|
+
def inherited(descendant) # :nodoc:
|
67
|
+
super
|
68
|
+
|
69
|
+
descendant_content_class = content_class.dup
|
70
|
+
|
71
|
+
if descendant_content_class.respond_to?(:set_temporary_name)
|
72
|
+
descendant_content_class.set_temporary_name("rendered_content")
|
73
|
+
end
|
74
|
+
|
75
|
+
descendant.content_class = descendant_content_class
|
76
|
+
end
|
77
|
+
|
78
|
+
# Register a callable to parse rendered content for a given template
|
79
|
+
# format.
|
80
|
+
#
|
81
|
+
# Each registered parser will also define a +#rendered.[FORMAT]+ helper
|
82
|
+
# method, where +[FORMAT]+ corresponds to the value of the
|
83
|
+
# +format+ argument.
|
84
|
+
#
|
85
|
+
# === Arguments
|
86
|
+
#
|
87
|
+
# <tt>format</tt> - Symbol the name of the format used to render view's content
|
88
|
+
# <tt>callable</tt> - Callable to parse the String. Accepts the String.
|
89
|
+
# value as its only argument.
|
90
|
+
# <tt>block</tt> - Block serves as the parser when the
|
91
|
+
# <tt>callable</tt> is omitted.
|
92
|
+
#
|
93
|
+
# By default, ActionView::TestCase defines a parser for:
|
94
|
+
#
|
95
|
+
# * :html - returns an instance of Nokogiri::XML::Node
|
96
|
+
# * :json - returns an instance of ActiveSupport::HashWithIndifferentAccess
|
97
|
+
#
|
98
|
+
# Each pre-registered parser also defines a corresponding helper:
|
99
|
+
#
|
100
|
+
# * :html - defines `rendered.html`
|
101
|
+
# * :json - defines `rendered.json`
|
102
|
+
#
|
103
|
+
# === Examples
|
104
|
+
#
|
105
|
+
# test "renders HTML" do
|
106
|
+
# article = Article.create!(title: "Hello, world")
|
107
|
+
#
|
108
|
+
# render partial: "articles/article", locals: { article: article }
|
109
|
+
#
|
110
|
+
# assert_pattern { rendered.html.at("main h1") => { content: "Hello, world" } }
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# test "renders JSON" do
|
114
|
+
# article = Article.create!(title: "Hello, world")
|
115
|
+
#
|
116
|
+
# render formats: :json, partial: "articles/article", locals: { article: article }
|
117
|
+
#
|
118
|
+
# assert_pattern { rendered.json => { title: "Hello, world" } }
|
119
|
+
# end
|
120
|
+
#
|
121
|
+
# To parse the rendered content into RSS, register a call to <tt>RSS::Parser.parse</tt>:
|
122
|
+
#
|
123
|
+
# register_parser :rss, -> rendered { RSS::Parser.parse(rendered) }
|
124
|
+
#
|
125
|
+
# test "renders RSS" do
|
126
|
+
# article = Article.create!(title: "Hello, world")
|
127
|
+
#
|
128
|
+
# render formats: :rss, partial: article
|
129
|
+
#
|
130
|
+
# assert_equal "Hello, world", rendered.rss.items.last.title
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
# To parse the rendered content into a Capybara::Simple::Node,
|
134
|
+
# re-register an <tt>:html</tt> parser with a call to
|
135
|
+
# <tt>Capybara.string</tt>:
|
136
|
+
#
|
137
|
+
# register_parser :html, -> rendered { Capybara.string(rendered) }
|
138
|
+
#
|
139
|
+
# test "renders HTML" do
|
140
|
+
# article = Article.create!(title: "Hello, world")
|
141
|
+
#
|
142
|
+
# render partial: article
|
143
|
+
#
|
144
|
+
# rendered.html.assert_css "h1", text: "Hello, world"
|
145
|
+
# end
|
146
|
+
def register_parser(format, callable = nil, &block)
|
147
|
+
parser = callable || block || :itself.to_proc
|
148
|
+
content_class.redefine_method(format) do
|
149
|
+
parser.call(to_s)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
63
153
|
def tests(helper_class)
|
64
154
|
case helper_class
|
65
155
|
when String, Symbol
|
@@ -105,14 +195,33 @@ module ActionView
|
|
105
195
|
end
|
106
196
|
end
|
107
197
|
|
198
|
+
included do
|
199
|
+
class_attribute :content_class, instance_accessor: false, default: Content
|
200
|
+
|
201
|
+
setup :setup_with_controller
|
202
|
+
|
203
|
+
register_parser :html, -> rendered { Rails::Dom::Testing.html_document.parse(rendered).root }
|
204
|
+
register_parser :json, -> rendered { JSON.parse(rendered, object_class: ActiveSupport::HashWithIndifferentAccess) }
|
205
|
+
|
206
|
+
ActiveSupport.run_load_hooks(:action_view_test_case, self)
|
207
|
+
|
208
|
+
helper do
|
209
|
+
def protect_against_forgery?
|
210
|
+
false
|
211
|
+
end
|
212
|
+
|
213
|
+
def _test_case
|
214
|
+
controller._test_case
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
108
219
|
def setup_with_controller
|
109
220
|
controller_class = Class.new(ActionView::TestCase::TestController)
|
110
221
|
@controller = controller_class.new
|
111
222
|
@request = @controller.request
|
112
223
|
@view_flow = ActionView::OutputFlow.new
|
113
|
-
|
114
|
-
# new without arguments returns ASCII-8BIT encoded buffer like String#new
|
115
|
-
@output_buffer = ActiveSupport::SafeBuffer.new ""
|
224
|
+
@output_buffer = ActionView::OutputBuffer.new
|
116
225
|
@rendered = +""
|
117
226
|
|
118
227
|
test_case_instance = self
|
@@ -133,10 +242,64 @@ module ActionView
|
|
133
242
|
@_rendered_views ||= RenderedViewsCollection.new
|
134
243
|
end
|
135
244
|
|
245
|
+
# Returns the content rendered by the last +render+ call.
|
246
|
+
#
|
247
|
+
# The returned object behaves like a string but also exposes a number of methods
|
248
|
+
# that allows you to parse the content string in formats registered using
|
249
|
+
# <tt>.register_parser</tt>.
|
250
|
+
#
|
251
|
+
# By default includes the following parsers:
|
252
|
+
#
|
253
|
+
# +.html+
|
254
|
+
#
|
255
|
+
# Parse the <tt>rendered</tt> content String into HTML. By default, this means
|
256
|
+
# a <tt>Nokogiri::XML::Node</tt>.
|
257
|
+
#
|
258
|
+
# test "renders HTML" do
|
259
|
+
# article = Article.create!(title: "Hello, world")
|
260
|
+
#
|
261
|
+
# render partial: "articles/article", locals: { article: article }
|
262
|
+
#
|
263
|
+
# assert_pattern { rendered.html.at("main h1") => { content: "Hello, world" } }
|
264
|
+
# end
|
265
|
+
#
|
266
|
+
# To parse the rendered content into a <tt>Capybara::Simple::Node</tt>,
|
267
|
+
# re-register an <tt>:html</tt> parser with a call to
|
268
|
+
# <tt>Capybara.string</tt>:
|
269
|
+
#
|
270
|
+
# register_parser :html, -> rendered { Capybara.string(rendered) }
|
271
|
+
#
|
272
|
+
# test "renders HTML" do
|
273
|
+
# article = Article.create!(title: "Hello, world")
|
274
|
+
#
|
275
|
+
# render partial: article
|
276
|
+
#
|
277
|
+
# rendered.html.assert_css "h1", text: "Hello, world"
|
278
|
+
# end
|
279
|
+
#
|
280
|
+
# +.json+
|
281
|
+
#
|
282
|
+
# Parse the <tt>rendered</tt> content String into JSON. By default, this means
|
283
|
+
# a <tt>ActiveSupport::HashWithIndifferentAccess</tt>.
|
284
|
+
#
|
285
|
+
# test "renders JSON" do
|
286
|
+
# article = Article.create!(title: "Hello, world")
|
287
|
+
#
|
288
|
+
# render formats: :json, partial: "articles/article", locals: { article: article }
|
289
|
+
#
|
290
|
+
# assert_pattern { rendered.json => { title: "Hello, world" } }
|
291
|
+
# end
|
292
|
+
def rendered
|
293
|
+
@_rendered ||= self.class.content_class.new(@rendered)
|
294
|
+
end
|
295
|
+
|
136
296
|
def _routes
|
137
297
|
@controller._routes if @controller.respond_to?(:_routes)
|
138
298
|
end
|
139
299
|
|
300
|
+
class Content < SimpleDelegator
|
301
|
+
end
|
302
|
+
|
140
303
|
# Need to experiment if this priority is the best one: rendered => output_buffer
|
141
304
|
class RenderedViewsCollection
|
142
305
|
def initialize
|
@@ -163,25 +326,10 @@ module ActionView
|
|
163
326
|
end
|
164
327
|
end
|
165
328
|
|
166
|
-
included do
|
167
|
-
setup :setup_with_controller
|
168
|
-
ActiveSupport.run_load_hooks(:action_view_test_case, self)
|
169
|
-
|
170
|
-
helper do
|
171
|
-
def protect_against_forgery?
|
172
|
-
false
|
173
|
-
end
|
174
|
-
|
175
|
-
def _test_case
|
176
|
-
controller._test_case
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
329
|
private
|
182
330
|
# Need to experiment if this priority is the best one: rendered => output_buffer
|
183
331
|
def document_root_element
|
184
|
-
|
332
|
+
Rails::Dom::Testing.html_document.parse(@rendered.blank? ? @output_buffer.to_str : @rendered).root
|
185
333
|
end
|
186
334
|
|
187
335
|
module Locals
|
@@ -227,6 +375,10 @@ module ActionView
|
|
227
375
|
:@_result,
|
228
376
|
:@_routes,
|
229
377
|
:@controller,
|
378
|
+
:@_controller,
|
379
|
+
:@_request,
|
380
|
+
:@_config,
|
381
|
+
:@_default_form_builder,
|
230
382
|
:@_layouts,
|
231
383
|
:@_files,
|
232
384
|
:@_rendered_views,
|
@@ -245,7 +397,7 @@ module ActionView
|
|
245
397
|
:@view_context_class,
|
246
398
|
:@view_flow,
|
247
399
|
:@_subscribers,
|
248
|
-
:@html_document
|
400
|
+
:@html_document,
|
249
401
|
]
|
250
402
|
|
251
403
|
def _user_defined_ivars
|
@@ -277,6 +429,7 @@ module ActionView
|
|
277
429
|
super
|
278
430
|
end
|
279
431
|
end
|
432
|
+
ruby2_keywords(:method_missing)
|
280
433
|
|
281
434
|
def respond_to_missing?(name, include_private = false)
|
282
435
|
begin
|
@@ -18,21 +18,31 @@ module ActionView
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def bind_locals(locals)
|
21
|
-
|
22
|
-
template
|
23
|
-
else
|
21
|
+
unless template = @templates[locals]
|
24
22
|
@write_lock.synchronize do
|
25
23
|
normalized_locals = normalize_locals(locals)
|
26
24
|
|
27
25
|
# We need ||=, both to dedup on the normalized locals and to check
|
28
26
|
# while holding the lock.
|
29
|
-
@templates[normalized_locals] ||= build_template(normalized_locals)
|
27
|
+
template = (@templates[normalized_locals] ||= build_template(normalized_locals))
|
30
28
|
|
31
29
|
# This may have already been assigned, but we've already de-dup'd so
|
32
30
|
# reassignment is fine.
|
33
|
-
@templates[locals.dup] =
|
31
|
+
@templates[locals.dup] = template
|
32
|
+
|
33
|
+
if template.strict_locals?
|
34
|
+
# Under strict locals, we only need one template.
|
35
|
+
# This replaces the @templates Concurrent::Map with a hash which
|
36
|
+
# returns this template for every key.
|
37
|
+
@templates = Hash.new(template).freeze
|
38
|
+
end
|
34
39
|
end
|
35
40
|
end
|
41
|
+
template
|
42
|
+
end
|
43
|
+
|
44
|
+
def built_templates # :nodoc:
|
45
|
+
@templates.values
|
36
46
|
end
|
37
47
|
|
38
48
|
private
|
data/lib/action_view/version.rb
CHANGED
@@ -5,7 +5,7 @@ module ActionView
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
|
8
|
+
ActionView::PathRegistry.set_view_paths(self, ActionView::PathSet.new.freeze)
|
9
9
|
end
|
10
10
|
|
11
11
|
delegate :template_exists?, :any_templates?, :view_paths, :formats, :formats=,
|
@@ -13,11 +13,11 @@ module ActionView
|
|
13
13
|
|
14
14
|
module ClassMethods
|
15
15
|
def _view_paths
|
16
|
-
|
16
|
+
ActionView::PathRegistry.get_view_paths(self)
|
17
17
|
end
|
18
18
|
|
19
19
|
def _view_paths=(paths)
|
20
|
-
|
20
|
+
ActionView::PathRegistry.set_view_paths(self, paths)
|
21
21
|
end
|
22
22
|
|
23
23
|
def _prefixes # :nodoc:
|
@@ -28,6 +28,13 @@ module ActionView
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
def _build_view_paths(paths) # :nodoc:
|
32
|
+
return paths if ActionView::PathSet === paths
|
33
|
+
|
34
|
+
paths = ActionView::PathRegistry.cast_file_system_resolvers(paths)
|
35
|
+
ActionView::PathSet.new(paths)
|
36
|
+
end
|
37
|
+
|
31
38
|
# Append a path to the list of view paths for this controller.
|
32
39
|
#
|
33
40
|
# ==== Parameters
|
@@ -35,7 +42,7 @@ module ActionView
|
|
35
42
|
# the default view path. You may also provide a custom view path
|
36
43
|
# (see ActionView::PathSet for more information)
|
37
44
|
def append_view_path(path)
|
38
|
-
self._view_paths = view_paths +
|
45
|
+
self._view_paths = view_paths + _build_view_paths(path)
|
39
46
|
end
|
40
47
|
|
41
48
|
# Prepend a path to the list of view paths for this controller.
|
@@ -45,7 +52,7 @@ module ActionView
|
|
45
52
|
# the default view path. You may also provide a custom view path
|
46
53
|
# (see ActionView::PathSet for more information)
|
47
54
|
def prepend_view_path(path)
|
48
|
-
self._view_paths =
|
55
|
+
self._view_paths = _build_view_paths(path) + view_paths
|
49
56
|
end
|
50
57
|
|
51
58
|
# A list of all of the default view paths for this controller.
|
@@ -59,7 +66,7 @@ module ActionView
|
|
59
66
|
# * <tt>paths</tt> - If a PathSet is provided, use that;
|
60
67
|
# otherwise, process the parameter into a PathSet.
|
61
68
|
def view_paths=(paths)
|
62
|
-
self._view_paths =
|
69
|
+
self._view_paths = _build_view_paths(paths)
|
63
70
|
end
|
64
71
|
|
65
72
|
private
|
@@ -70,30 +77,14 @@ module ActionView
|
|
70
77
|
end
|
71
78
|
end
|
72
79
|
|
73
|
-
# :stopdoc:
|
74
|
-
@all_view_paths = {}
|
75
|
-
|
76
|
-
def self.get_view_paths(klass)
|
77
|
-
@all_view_paths[klass] || get_view_paths(klass.superclass)
|
78
|
-
end
|
79
|
-
|
80
|
-
def self.set_view_paths(klass, paths)
|
81
|
-
@all_view_paths[klass] = paths
|
82
|
-
end
|
83
|
-
|
84
|
-
def self.all_view_paths
|
85
|
-
@all_view_paths.values.uniq
|
86
|
-
end
|
87
|
-
# :startdoc:
|
88
|
-
|
89
80
|
# The prefixes used in render "foo" shortcuts.
|
90
81
|
def _prefixes # :nodoc:
|
91
82
|
self.class._prefixes
|
92
83
|
end
|
93
84
|
|
94
|
-
#
|
85
|
+
# LookupContext is the object responsible for holding all
|
95
86
|
# information required for looking up templates, i.e. view paths and
|
96
|
-
# details. Check
|
87
|
+
# details. Check ActionView::LookupContext for more information.
|
97
88
|
def lookup_context
|
98
89
|
@_lookup_context ||=
|
99
90
|
ActionView::LookupContext.new(self.class._view_paths, details_for_lookup, _prefixes)
|
@@ -103,24 +94,24 @@ module ActionView
|
|
103
94
|
{}
|
104
95
|
end
|
105
96
|
|
106
|
-
# Append a path to the list of view paths for the current
|
97
|
+
# Append a path to the list of view paths for the current LookupContext.
|
107
98
|
#
|
108
99
|
# ==== Parameters
|
109
100
|
# * <tt>path</tt> - If a String is provided, it gets converted into
|
110
101
|
# the default view path. You may also provide a custom view path
|
111
102
|
# (see ActionView::PathSet for more information)
|
112
103
|
def append_view_path(path)
|
113
|
-
lookup_context.
|
104
|
+
lookup_context.append_view_paths(self.class._build_view_paths(path))
|
114
105
|
end
|
115
106
|
|
116
|
-
# Prepend a path to the list of view paths for the current
|
107
|
+
# Prepend a path to the list of view paths for the current LookupContext.
|
117
108
|
#
|
118
109
|
# ==== Parameters
|
119
110
|
# * <tt>path</tt> - If a String is provided, it gets converted into
|
120
111
|
# the default view path. You may also provide a custom view path
|
121
112
|
# (see ActionView::PathSet for more information)
|
122
113
|
def prepend_view_path(path)
|
123
|
-
lookup_context.
|
114
|
+
lookup_context.prepend_view_paths(self.class._build_view_paths(path))
|
124
115
|
end
|
125
116
|
end
|
126
117
|
end
|
data/lib/action_view.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (c)
|
4
|
+
# Copyright (c) David Heinemeier Hansson
|
5
5
|
#
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
7
7
|
# a copy of this software and associated documentation files (the
|
@@ -26,7 +26,9 @@
|
|
26
26
|
require "active_support"
|
27
27
|
require "active_support/rails"
|
28
28
|
require "action_view/version"
|
29
|
+
require "action_view/deprecator"
|
29
30
|
|
31
|
+
# :include: actionview/README.rdoc
|
30
32
|
module ActionView
|
31
33
|
extend ActiveSupport::Autoload
|
32
34
|
|
@@ -39,6 +41,7 @@ module ActionView
|
|
39
41
|
autoload :Helpers
|
40
42
|
autoload :LookupContext
|
41
43
|
autoload :Layouts
|
44
|
+
autoload :PathRegistry
|
42
45
|
autoload :PathSet
|
43
46
|
autoload :RecordIdentifier
|
44
47
|
autoload :Rendering
|
@@ -73,6 +73,22 @@ Released under the MIT license
|
|
73
73
|
return element[expando][key] = value;
|
74
74
|
};
|
75
75
|
|
76
|
+
Rails.isContentEditable = function(element) {
|
77
|
+
var isEditable;
|
78
|
+
isEditable = false;
|
79
|
+
while (true) {
|
80
|
+
if (element.isContentEditable) {
|
81
|
+
isEditable = true;
|
82
|
+
break;
|
83
|
+
}
|
84
|
+
element = element.parentElement;
|
85
|
+
if (!element) {
|
86
|
+
break;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
return isEditable;
|
90
|
+
};
|
91
|
+
|
76
92
|
Rails.$ = function(selector) {
|
77
93
|
return Array.prototype.slice.call(document.querySelectorAll(selector));
|
78
94
|
};
|
@@ -395,9 +411,9 @@ Released under the MIT license
|
|
395
411
|
|
396
412
|
}).call(this);
|
397
413
|
(function() {
|
398
|
-
var disableFormElement, disableFormElements, disableLinkElement, enableFormElement, enableFormElements, enableLinkElement, formElements, getData, isXhrRedirect, matches, setData, stopEverything;
|
414
|
+
var disableFormElement, disableFormElements, disableLinkElement, enableFormElement, enableFormElements, enableLinkElement, formElements, getData, isContentEditable, isXhrRedirect, matches, setData, stopEverything;
|
399
415
|
|
400
|
-
matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, stopEverything = Rails.stopEverything, formElements = Rails.formElements;
|
416
|
+
matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, stopEverything = Rails.stopEverything, formElements = Rails.formElements, isContentEditable = Rails.isContentEditable;
|
401
417
|
|
402
418
|
Rails.handleDisabledElement = function(e) {
|
403
419
|
var element;
|
@@ -417,6 +433,9 @@ Released under the MIT license
|
|
417
433
|
} else {
|
418
434
|
element = e;
|
419
435
|
}
|
436
|
+
if (isContentEditable(element)) {
|
437
|
+
return;
|
438
|
+
}
|
420
439
|
if (matches(element, Rails.linkDisableSelector)) {
|
421
440
|
return enableLinkElement(element);
|
422
441
|
} else if (matches(element, Rails.buttonDisableSelector) || matches(element, Rails.formEnableSelector)) {
|
@@ -429,6 +448,9 @@ Released under the MIT license
|
|
429
448
|
Rails.disableElement = function(e) {
|
430
449
|
var element;
|
431
450
|
element = e instanceof Event ? e.target : e;
|
451
|
+
if (isContentEditable(element)) {
|
452
|
+
return;
|
453
|
+
}
|
432
454
|
if (matches(element, Rails.linkDisableSelector)) {
|
433
455
|
return disableLinkElement(element);
|
434
456
|
} else if (matches(element, Rails.buttonDisableSelector) || matches(element, Rails.formDisableSelector)) {
|
@@ -513,10 +535,12 @@ Released under the MIT license
|
|
513
535
|
|
514
536
|
}).call(this);
|
515
537
|
(function() {
|
516
|
-
var stopEverything;
|
538
|
+
var isContentEditable, stopEverything;
|
517
539
|
|
518
540
|
stopEverything = Rails.stopEverything;
|
519
541
|
|
542
|
+
isContentEditable = Rails.isContentEditable;
|
543
|
+
|
520
544
|
Rails.handleMethod = function(e) {
|
521
545
|
var csrfParam, csrfToken, form, formContent, href, link, method;
|
522
546
|
link = this;
|
@@ -524,6 +548,9 @@ Released under the MIT license
|
|
524
548
|
if (!method) {
|
525
549
|
return;
|
526
550
|
}
|
551
|
+
if (isContentEditable(this)) {
|
552
|
+
return;
|
553
|
+
}
|
527
554
|
href = Rails.href(link);
|
528
555
|
csrfToken = Rails.csrfToken();
|
529
556
|
csrfParam = Rails.csrfParam();
|
@@ -545,10 +572,10 @@ Released under the MIT license
|
|
545
572
|
|
546
573
|
}).call(this);
|
547
574
|
(function() {
|
548
|
-
var ajax, fire, getData, isCrossDomain, isRemote, matches, serializeElement, setData, stopEverything,
|
575
|
+
var ajax, fire, getData, isContentEditable, isCrossDomain, isRemote, matches, serializeElement, setData, stopEverything,
|
549
576
|
slice = [].slice;
|
550
577
|
|
551
|
-
matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, fire = Rails.fire, stopEverything = Rails.stopEverything, ajax = Rails.ajax, isCrossDomain = Rails.isCrossDomain, serializeElement = Rails.serializeElement;
|
578
|
+
matches = Rails.matches, getData = Rails.getData, setData = Rails.setData, fire = Rails.fire, stopEverything = Rails.stopEverything, ajax = Rails.ajax, isCrossDomain = Rails.isCrossDomain, serializeElement = Rails.serializeElement, isContentEditable = Rails.isContentEditable;
|
552
579
|
|
553
580
|
isRemote = function(element) {
|
554
581
|
var value;
|
@@ -566,6 +593,10 @@ Released under the MIT license
|
|
566
593
|
fire(element, 'ajax:stopped');
|
567
594
|
return false;
|
568
595
|
}
|
596
|
+
if (isContentEditable(element)) {
|
597
|
+
fire(element, 'ajax:stopped');
|
598
|
+
return false;
|
599
|
+
}
|
569
600
|
withCredentials = element.getAttribute('data-with-credentials');
|
570
601
|
dataType = element.getAttribute('data-type') || 'script';
|
571
602
|
if (matches(element, Rails.formSubmitSelector)) {
|