actionview 6.1.7.10 → 7.0.0.alpha1
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 +89 -409
- data/MIT-LICENSE +2 -1
- data/lib/action_view/base.rb +3 -3
- data/lib/action_view/buffers.rb +2 -2
- data/lib/action_view/cache_expiry.rb +46 -32
- data/lib/action_view/dependency_tracker/erb_tracker.rb +154 -0
- data/lib/action_view/dependency_tracker/ripper_tracker.rb +59 -0
- data/lib/action_view/dependency_tracker.rb +6 -147
- data/lib/action_view/digestor.rb +7 -4
- data/lib/action_view/flows.rb +4 -4
- data/lib/action_view/gem_version.rb +4 -4
- data/lib/action_view/helpers/active_model_helper.rb +1 -1
- data/lib/action_view/helpers/asset_tag_helper.rb +84 -29
- data/lib/action_view/helpers/asset_url_helper.rb +7 -7
- data/lib/action_view/helpers/atom_feed_helper.rb +3 -4
- data/lib/action_view/helpers/cache_helper.rb +51 -3
- data/lib/action_view/helpers/capture_helper.rb +2 -2
- data/lib/action_view/helpers/controller_helper.rb +2 -2
- data/lib/action_view/helpers/csp_helper.rb +1 -1
- data/lib/action_view/helpers/csrf_helper.rb +1 -1
- data/lib/action_view/helpers/date_helper.rb +6 -7
- data/lib/action_view/helpers/debug_helper.rb +3 -1
- data/lib/action_view/helpers/form_helper.rb +72 -12
- data/lib/action_view/helpers/form_options_helper.rb +65 -33
- data/lib/action_view/helpers/form_tag_helper.rb +75 -32
- data/lib/action_view/helpers/javascript_helper.rb +3 -5
- data/lib/action_view/helpers/number_helper.rb +3 -4
- data/lib/action_view/helpers/output_safety_helper.rb +2 -2
- data/lib/action_view/helpers/rendering_helper.rb +1 -1
- data/lib/action_view/helpers/sanitize_helper.rb +2 -2
- data/lib/action_view/helpers/tag_helper.rb +25 -44
- data/lib/action_view/helpers/tags/base.rb +3 -15
- data/lib/action_view/helpers/tags/check_box.rb +2 -2
- data/lib/action_view/helpers/tags/collection_select.rb +1 -1
- data/lib/action_view/helpers/tags/hidden_field.rb +0 -4
- data/lib/action_view/helpers/tags/time_field.rb +10 -1
- data/lib/action_view/helpers/tags/weekday_select.rb +27 -0
- data/lib/action_view/helpers/tags.rb +3 -2
- data/lib/action_view/helpers/text_helper.rb +24 -13
- data/lib/action_view/helpers/translation_helper.rb +1 -2
- data/lib/action_view/helpers/url_helper.rb +102 -77
- data/lib/action_view/helpers.rb +25 -25
- data/lib/action_view/lookup_context.rb +33 -52
- data/lib/action_view/model_naming.rb +1 -1
- data/lib/action_view/path_set.rb +16 -22
- data/lib/action_view/railtie.rb +14 -1
- data/lib/action_view/render_parser.rb +188 -0
- data/lib/action_view/renderer/abstract_renderer.rb +2 -2
- data/lib/action_view/renderer/partial_renderer.rb +0 -34
- data/lib/action_view/renderer/renderer.rb +4 -4
- data/lib/action_view/renderer/streaming_template_renderer.rb +3 -3
- data/lib/action_view/renderer/template_renderer.rb +6 -2
- data/lib/action_view/rendering.rb +2 -2
- data/lib/action_view/ripper_ast_parser.rb +198 -0
- data/lib/action_view/routing_url_for.rb +1 -1
- data/lib/action_view/template/error.rb +108 -13
- data/lib/action_view/template/handlers/erb.rb +6 -0
- data/lib/action_view/template/handlers.rb +3 -3
- data/lib/action_view/template/html.rb +3 -3
- data/lib/action_view/template/inline.rb +3 -3
- data/lib/action_view/template/raw_file.rb +3 -3
- data/lib/action_view/template/resolver.rb +84 -311
- data/lib/action_view/template/text.rb +3 -3
- data/lib/action_view/template/types.rb +14 -12
- data/lib/action_view/template.rb +10 -1
- data/lib/action_view/template_details.rb +66 -0
- data/lib/action_view/template_path.rb +64 -0
- data/lib/action_view/test_case.rb +6 -2
- data/lib/action_view/testing/resolvers.rb +11 -12
- data/lib/action_view/unbound_template.rb +33 -7
- data/lib/action_view.rb +3 -4
- data/lib/assets/compiled/rails-ujs.js +5 -36
- metadata +22 -16
@@ -1,15 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/enumerable"
|
3
4
|
require "active_support/core_ext/string/output_safety"
|
4
5
|
require "set"
|
6
|
+
require "action_view/helpers/capture_helper"
|
7
|
+
require "action_view/helpers/output_safety_helper"
|
5
8
|
|
6
9
|
module ActionView
|
7
10
|
# = Action View Tag Helpers
|
8
|
-
module Helpers
|
11
|
+
module Helpers # :nodoc:
|
9
12
|
# Provides methods to generate HTML tags programmatically both as a modern
|
10
13
|
# HTML5 compliant builder style and legacy XHTML compliant tags.
|
11
14
|
module TagHelper
|
12
|
-
extend ActiveSupport::Concern
|
13
15
|
include CaptureHelper
|
14
16
|
include OutputSafetyHelper
|
15
17
|
|
@@ -39,7 +41,7 @@ module ActionView
|
|
39
41
|
PRE_CONTENT_STRINGS[:textarea] = "\n"
|
40
42
|
PRE_CONTENT_STRINGS["textarea"] = "\n"
|
41
43
|
|
42
|
-
class TagBuilder
|
44
|
+
class TagBuilder # :nodoc:
|
43
45
|
include CaptureHelper
|
44
46
|
include OutputSafetyHelper
|
45
47
|
|
@@ -49,29 +51,31 @@ module ActionView
|
|
49
51
|
@view_context = view_context
|
50
52
|
end
|
51
53
|
|
54
|
+
# Transforms a Hash into HTML Attributes, ready to be interpolated into
|
55
|
+
# ERB.
|
56
|
+
#
|
57
|
+
# <input <%= tag.attributes(type: :text, aria: { label: "Search" }) %> >
|
58
|
+
# # => <input type="text" aria-label="Search">
|
59
|
+
def attributes(attributes)
|
60
|
+
tag_options(attributes.to_h).to_s.strip.html_safe
|
61
|
+
end
|
62
|
+
|
52
63
|
def p(*arguments, **options, &block)
|
53
64
|
tag_string(:p, *arguments, **options, &block)
|
54
65
|
end
|
55
66
|
|
56
|
-
def tag_string(name, content = nil, **options, &block)
|
57
|
-
escape = handle_deprecated_escape_options(options)
|
58
|
-
|
67
|
+
def tag_string(name, content = nil, escape_attributes: true, **options, &block)
|
59
68
|
content = @view_context.capture(self, &block) if block_given?
|
60
69
|
if VOID_ELEMENTS.include?(name) && content.nil?
|
61
|
-
"<#{name.to_s.dasherize}#{tag_options(options,
|
70
|
+
"<#{name.to_s.dasherize}#{tag_options(options, escape_attributes)}>".html_safe
|
62
71
|
else
|
63
|
-
content_tag_string(name.to_s.dasherize, content || "", options,
|
72
|
+
content_tag_string(name.to_s.dasherize, content || "", options, escape_attributes)
|
64
73
|
end
|
65
74
|
end
|
66
75
|
|
67
76
|
def content_tag_string(name, content, options, escape = true)
|
68
77
|
tag_options = tag_options(options, escape) if options
|
69
|
-
|
70
|
-
if escape
|
71
|
-
name = ERB::Util.xml_name_escape(name)
|
72
|
-
content = ERB::Util.unwrapped_html_escape(content)
|
73
|
-
end
|
74
|
-
|
78
|
+
content = ERB::Util.unwrapped_html_escape(content) if escape
|
75
79
|
"<#{name}#{tag_options}>#{PRE_CONTENT_STRINGS[name]}#{content}</#{name}>".html_safe
|
76
80
|
end
|
77
81
|
|
@@ -122,17 +126,16 @@ module ActionView
|
|
122
126
|
end
|
123
127
|
|
124
128
|
def tag_option(key, value, escape)
|
125
|
-
key = ERB::Util.xml_name_escape(key) if escape
|
126
|
-
|
127
129
|
case value
|
128
130
|
when Array, Hash
|
129
131
|
value = TagHelper.build_tag_values(value) if key.to_s == "class"
|
130
132
|
value = escape ? safe_join(value, " ") : value.join(" ")
|
133
|
+
when Regexp
|
134
|
+
value = escape ? ERB::Util.unwrapped_html_escape(value.source) : value.source
|
131
135
|
else
|
132
136
|
value = escape ? ERB::Util.unwrapped_html_escape(value) : value.to_s
|
133
137
|
end
|
134
138
|
value = value.gsub('"', """) if value.include?('"')
|
135
|
-
|
136
139
|
%(#{key}="#{value}")
|
137
140
|
end
|
138
141
|
|
@@ -149,27 +152,6 @@ module ActionView
|
|
149
152
|
true
|
150
153
|
end
|
151
154
|
|
152
|
-
def handle_deprecated_escape_options(options)
|
153
|
-
# The option :escape_attributes has been merged into the options hash to be
|
154
|
-
# able to warn when it is used, so we need to handle default values here.
|
155
|
-
escape_option_provided = options.has_key?(:escape)
|
156
|
-
escape_attributes_option_provided = options.has_key?(:escape_attributes)
|
157
|
-
|
158
|
-
if escape_attributes_option_provided
|
159
|
-
ActiveSupport::Deprecation.warn(<<~MSG)
|
160
|
-
Use of the option :escape_attributes is deprecated. It currently \
|
161
|
-
escapes both names and values of tags and attributes and it is \
|
162
|
-
equivalent to :escape. If any of them are enabled, the escaping \
|
163
|
-
is fully enabled.
|
164
|
-
MSG
|
165
|
-
end
|
166
|
-
|
167
|
-
return true unless escape_option_provided || escape_attributes_option_provided
|
168
|
-
escape_option = options.delete(:escape)
|
169
|
-
escape_attributes_option = options.delete(:escape_attributes)
|
170
|
-
escape_option || escape_attributes_option
|
171
|
-
end
|
172
|
-
|
173
155
|
def method_missing(called, *args, **options, &block)
|
174
156
|
tag_string(called, *args, **options, &block)
|
175
157
|
end
|
@@ -233,13 +215,13 @@ module ActionView
|
|
233
215
|
# tag.div data: { city_state: %w( Chicago IL ) }
|
234
216
|
# # => <div data-city-state="["Chicago","IL"]"></div>
|
235
217
|
#
|
236
|
-
# The generated
|
237
|
-
# +
|
218
|
+
# The generated attributes are escaped by default. This can be disabled using
|
219
|
+
# +escape_attributes+.
|
238
220
|
#
|
239
221
|
# tag.img src: 'open & shut.png'
|
240
222
|
# # => <img src="open & shut.png">
|
241
223
|
#
|
242
|
-
# tag.img src: 'open & shut.png',
|
224
|
+
# tag.img src: 'open & shut.png', escape_attributes: false
|
243
225
|
# # => <img src="open & shut.png">
|
244
226
|
#
|
245
227
|
# The tag builder respects
|
@@ -303,7 +285,6 @@ module ActionView
|
|
303
285
|
if name.nil?
|
304
286
|
tag_builder
|
305
287
|
else
|
306
|
-
name = ERB::Util.xml_name_escape(name) if escape
|
307
288
|
"<#{name}#{tag_builder.tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe
|
308
289
|
end
|
309
290
|
end
|
@@ -312,7 +293,7 @@ module ActionView
|
|
312
293
|
# HTML attributes by passing an attributes hash to +options+.
|
313
294
|
# Instead of passing the content as an argument, you can also use a block
|
314
295
|
# in which case, you pass your +options+ as the second parameter.
|
315
|
-
# Set escape to false to disable escaping.
|
296
|
+
# Set escape to false to disable attribute value escaping.
|
316
297
|
# Note: this is legacy syntax, see +tag+ method description for details.
|
317
298
|
#
|
318
299
|
# ==== Options
|
@@ -377,7 +358,7 @@ module ActionView
|
|
377
358
|
# cdata_section("hello]]>world")
|
378
359
|
# # => <![CDATA[hello]]]]><![CDATA[>world]]>
|
379
360
|
def cdata_section(content)
|
380
|
-
splitted = content.to_s.gsub(/\]\]
|
361
|
+
splitted = content.to_s.gsub(/\]\]>/, "]]]]><![CDATA[>")
|
381
362
|
"<![CDATA[#{splitted}]]>".html_safe
|
382
363
|
end
|
383
364
|
|
@@ -117,19 +117,7 @@ module ActionView
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def tag_id(index = nil)
|
120
|
-
|
121
|
-
case
|
122
|
-
when @object_name.empty?
|
123
|
-
sanitized_method_name.dup
|
124
|
-
when index
|
125
|
-
"#{sanitized_object_name}_#{index}_#{sanitized_method_name}"
|
126
|
-
else
|
127
|
-
"#{sanitized_object_name}_#{sanitized_method_name}"
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def sanitized_object_name
|
132
|
-
@sanitized_object_name ||= @object_name.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").delete_suffix("_")
|
120
|
+
@template_object.field_id(@object_name, @method_name, index: index)
|
133
121
|
end
|
134
122
|
|
135
123
|
def sanitized_method_name
|
@@ -137,7 +125,7 @@ module ActionView
|
|
137
125
|
end
|
138
126
|
|
139
127
|
def sanitized_value(value)
|
140
|
-
value.to_s.gsub(/[\s
|
128
|
+
value.to_s.gsub(/[\s.]/, "_").gsub(/[^-[[:word:]]]/, "").downcase
|
141
129
|
end
|
142
130
|
|
143
131
|
def select_content_tag(option_tags, options, html_options)
|
@@ -153,7 +141,7 @@ module ActionView
|
|
153
141
|
select = content_tag("select", add_options(option_tags, options, value), html_options)
|
154
142
|
|
155
143
|
if html_options["multiple"] && options.fetch(:include_hidden, true)
|
156
|
-
tag("input", disabled: html_options["disabled"], name: html_options["name"], type: "hidden", value: ""
|
144
|
+
tag("input", disabled: html_options["disabled"], name: html_options["name"], type: "hidden", value: "") + select
|
157
145
|
else
|
158
146
|
select
|
159
147
|
end
|
@@ -5,7 +5,7 @@ require "action_view/helpers/tags/checkable"
|
|
5
5
|
module ActionView
|
6
6
|
module Helpers
|
7
7
|
module Tags # :nodoc:
|
8
|
-
class CheckBox < Base
|
8
|
+
class CheckBox < Base # :nodoc:
|
9
9
|
include Checkable
|
10
10
|
|
11
11
|
def initialize(object_name, method_name, template_object, checked_value, unchecked_value, options)
|
@@ -57,7 +57,7 @@ module ActionView
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def hidden_field_for_checkbox(options)
|
60
|
-
@unchecked_value ? tag("input", options.slice("name", "disabled", "form").merge!("type" => "hidden", "value" => @unchecked_value
|
60
|
+
@unchecked_value ? tag("input", options.slice("name", "disabled", "form").merge!("type" => "hidden", "value" => @unchecked_value)) : "".html_safe
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module ActionView
|
4
4
|
module Helpers
|
5
5
|
module Tags # :nodoc:
|
6
|
-
class CollectionSelect < Base
|
6
|
+
class CollectionSelect < Base # :nodoc:
|
7
7
|
def initialize(object_name, method_name, template_object, collection, value_method, text_method, options, html_options)
|
8
8
|
@collection = collection
|
9
9
|
@value_method = value_method
|
@@ -4,9 +4,18 @@ module ActionView
|
|
4
4
|
module Helpers
|
5
5
|
module Tags # :nodoc:
|
6
6
|
class TimeField < DatetimeField # :nodoc:
|
7
|
+
def initialize(object_name, method_name, template_object, options = {})
|
8
|
+
@include_seconds = options.delete(:include_seconds) { true }
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
7
12
|
private
|
8
13
|
def format_date(value)
|
9
|
-
|
14
|
+
if @include_seconds
|
15
|
+
value&.strftime("%T.%L")
|
16
|
+
else
|
17
|
+
value&.strftime("%H:%M")
|
18
|
+
end
|
10
19
|
end
|
11
20
|
end
|
12
21
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionView
|
4
|
+
module Helpers
|
5
|
+
module Tags # :nodoc:
|
6
|
+
class WeekdaySelect < Base # :nodoc:
|
7
|
+
def initialize(object_name, method_name, template_object, options, html_options)
|
8
|
+
@html_options = html_options
|
9
|
+
|
10
|
+
super(object_name, method_name, template_object, options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def render
|
14
|
+
select_content_tag(
|
15
|
+
weekday_options_for_select(
|
16
|
+
value || @options[:selected],
|
17
|
+
index_as_value: @options.fetch(:index_as_value, false),
|
18
|
+
day_format: @options.fetch(:day_format, :day_names)
|
19
|
+
),
|
20
|
+
@options,
|
21
|
+
@html_options
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionView
|
4
|
-
module Helpers
|
5
|
-
module Tags
|
4
|
+
module Helpers # :nodoc:
|
5
|
+
module Tags # :nodoc:
|
6
6
|
extend ActiveSupport::Autoload
|
7
7
|
|
8
8
|
eager_autoload do
|
@@ -38,6 +38,7 @@ module ActionView
|
|
38
38
|
autoload :TimeZoneSelect
|
39
39
|
autoload :UrlField
|
40
40
|
autoload :WeekField
|
41
|
+
autoload :WeekdaySelect
|
41
42
|
end
|
42
43
|
end
|
43
44
|
end
|
@@ -1,11 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/core_ext/string/filters"
|
4
|
+
require "active_support/core_ext/string/access"
|
4
5
|
require "active_support/core_ext/array/extract_options"
|
6
|
+
require "action_view/helpers/sanitize_helper"
|
7
|
+
require "action_view/helpers/tag_helper"
|
8
|
+
require "action_view/helpers/output_safety_helper"
|
5
9
|
|
6
10
|
module ActionView
|
7
11
|
# = Action View Text Helpers
|
8
|
-
module Helpers
|
12
|
+
module Helpers # :nodoc:
|
9
13
|
# The TextHelper module provides a set of methods for filtering, formatting
|
10
14
|
# and transforming strings, which can reduce the amount of inline Ruby code in
|
11
15
|
# your views. These helper methods extend Action View making them callable
|
@@ -129,7 +133,7 @@ module ActionView
|
|
129
133
|
#
|
130
134
|
# highlight('<a href="javascript:alert(\'no!\')">ruby</a> on rails', 'rails', sanitize: false)
|
131
135
|
# # => <a href="javascript:alert('no!')">ruby</a> on <mark>rails</mark>
|
132
|
-
def highlight(text, phrases, options = {})
|
136
|
+
def highlight(text, phrases, options = {}, &block)
|
133
137
|
text = sanitize(text) if options.fetch(:sanitize, true)
|
134
138
|
|
135
139
|
if text.blank? || phrases.blank?
|
@@ -140,7 +144,7 @@ module ActionView
|
|
140
144
|
end.join("|")
|
141
145
|
|
142
146
|
if block_given?
|
143
|
-
text.gsub(/(#{match})(?![^<]*?>)/i)
|
147
|
+
text.gsub(/(#{match})(?![^<]*?>)/i, &block)
|
144
148
|
else
|
145
149
|
highlighter = options.fetch(:highlighter, '<mark>\1</mark>')
|
146
150
|
text.gsub(/(#{match})(?![^<]*?>)/i, highlighter)
|
@@ -403,7 +407,7 @@ module ActionView
|
|
403
407
|
cycle.reset if cycle
|
404
408
|
end
|
405
409
|
|
406
|
-
class Cycle
|
410
|
+
class Cycle # :nodoc:
|
407
411
|
attr_reader :values
|
408
412
|
|
409
413
|
def initialize(first_value, *values)
|
@@ -467,18 +471,25 @@ module ActionView
|
|
467
471
|
radius = options.fetch(:radius, 100)
|
468
472
|
omission = options.fetch(:omission, "...")
|
469
473
|
|
470
|
-
|
471
|
-
|
472
|
-
|
474
|
+
if separator != ""
|
475
|
+
part = part.split(separator)
|
476
|
+
part.delete("")
|
477
|
+
end
|
473
478
|
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
+
affix = part.length > radius ? omission : ""
|
480
|
+
|
481
|
+
part =
|
482
|
+
if part_position == :first
|
483
|
+
part.last(radius)
|
484
|
+
else
|
485
|
+
part.first(radius)
|
486
|
+
end
|
487
|
+
|
488
|
+
if separator != ""
|
489
|
+
part = part.join(separator)
|
479
490
|
end
|
480
491
|
|
481
|
-
return affix, part
|
492
|
+
return affix, part
|
482
493
|
end
|
483
494
|
end
|
484
495
|
end
|
@@ -1,11 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "action_view/helpers/tag_helper"
|
4
|
-
require "active_support/core_ext/symbol/starts_ends_with"
|
5
4
|
|
6
5
|
module ActionView
|
7
6
|
# = Action View Translation Helpers
|
8
|
-
module Helpers
|
7
|
+
module Helpers # :nodoc:
|
9
8
|
module TranslationHelper
|
10
9
|
extend ActiveSupport::Concern
|
11
10
|
|