actionview 7.0.1 → 7.1.1
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 +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)) {
|