actionview 6.1.7.2 → 7.1.3

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.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +299 -277
  3. data/MIT-LICENSE +2 -1
  4. data/README.rdoc +3 -3
  5. data/app/assets/javascripts/rails-ujs.esm.js +686 -0
  6. data/app/assets/javascripts/rails-ujs.js +630 -0
  7. data/lib/action_view/base.rb +37 -19
  8. data/lib/action_view/buffers.rb +107 -9
  9. data/lib/action_view/cache_expiry.rb +48 -37
  10. data/lib/action_view/context.rb +1 -1
  11. data/lib/action_view/dependency_tracker/erb_tracker.rb +154 -0
  12. data/lib/action_view/dependency_tracker/ripper_tracker.rb +59 -0
  13. data/lib/action_view/dependency_tracker.rb +6 -147
  14. data/lib/action_view/deprecator.rb +7 -0
  15. data/lib/action_view/digestor.rb +8 -5
  16. data/lib/action_view/flows.rb +4 -4
  17. data/lib/action_view/gem_version.rb +4 -4
  18. data/lib/action_view/helpers/active_model_helper.rb +3 -3
  19. data/lib/action_view/helpers/asset_tag_helper.rb +200 -60
  20. data/lib/action_view/helpers/asset_url_helper.rb +22 -21
  21. data/lib/action_view/helpers/atom_feed_helper.rb +8 -9
  22. data/lib/action_view/helpers/cache_helper.rb +55 -12
  23. data/lib/action_view/helpers/capture_helper.rb +34 -14
  24. data/lib/action_view/helpers/content_exfiltration_prevention_helper.rb +70 -0
  25. data/lib/action_view/helpers/controller_helper.rb +8 -2
  26. data/lib/action_view/helpers/csp_helper.rb +3 -3
  27. data/lib/action_view/helpers/csrf_helper.rb +4 -4
  28. data/lib/action_view/helpers/date_helper.rb +123 -57
  29. data/lib/action_view/helpers/debug_helper.rb +6 -4
  30. data/lib/action_view/helpers/form_helper.rb +253 -97
  31. data/lib/action_view/helpers/form_options_helper.rb +72 -34
  32. data/lib/action_view/helpers/form_tag_helper.rb +189 -58
  33. data/lib/action_view/helpers/javascript_helper.rb +4 -5
  34. data/lib/action_view/helpers/number_helper.rb +43 -335
  35. data/lib/action_view/helpers/output_safety_helper.rb +6 -6
  36. data/lib/action_view/helpers/rendering_helper.rb +6 -7
  37. data/lib/action_view/helpers/sanitize_helper.rb +54 -24
  38. data/lib/action_view/helpers/tag_helper.rb +42 -35
  39. data/lib/action_view/helpers/tags/base.rb +16 -77
  40. data/lib/action_view/helpers/tags/check_box.rb +1 -1
  41. data/lib/action_view/helpers/tags/collection_check_boxes.rb +1 -0
  42. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +1 -0
  43. data/lib/action_view/helpers/tags/collection_select.rb +4 -1
  44. data/lib/action_view/helpers/tags/date_field.rb +1 -1
  45. data/lib/action_view/helpers/tags/date_select.rb +2 -0
  46. data/lib/action_view/helpers/tags/datetime_field.rb +14 -6
  47. data/lib/action_view/helpers/tags/datetime_local_field.rb +11 -2
  48. data/lib/action_view/helpers/tags/file_field.rb +16 -0
  49. data/lib/action_view/helpers/tags/grouped_collection_select.rb +3 -0
  50. data/lib/action_view/helpers/tags/month_field.rb +1 -1
  51. data/lib/action_view/helpers/tags/select.rb +4 -1
  52. data/lib/action_view/helpers/tags/select_renderer.rb +56 -0
  53. data/lib/action_view/helpers/tags/time_field.rb +11 -2
  54. data/lib/action_view/helpers/tags/time_zone_select.rb +3 -0
  55. data/lib/action_view/helpers/tags/week_field.rb +1 -1
  56. data/lib/action_view/helpers/tags/weekday_select.rb +31 -0
  57. data/lib/action_view/helpers/tags.rb +5 -2
  58. data/lib/action_view/helpers/text_helper.rb +180 -97
  59. data/lib/action_view/helpers/translation_helper.rb +14 -45
  60. data/lib/action_view/helpers/url_helper.rb +230 -132
  61. data/lib/action_view/helpers.rb +27 -25
  62. data/lib/action_view/layouts.rb +15 -10
  63. data/lib/action_view/log_subscriber.rb +49 -32
  64. data/lib/action_view/lookup_context.rb +58 -61
  65. data/lib/action_view/model_naming.rb +2 -2
  66. data/lib/action_view/path_registry.rb +57 -0
  67. data/lib/action_view/path_set.rb +28 -35
  68. data/lib/action_view/railtie.rb +44 -9
  69. data/lib/action_view/record_identifier.rb +16 -9
  70. data/lib/action_view/render_parser.rb +188 -0
  71. data/lib/action_view/renderer/abstract_renderer.rb +3 -3
  72. data/lib/action_view/renderer/collection_renderer.rb +10 -2
  73. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +21 -3
  74. data/lib/action_view/renderer/partial_renderer.rb +3 -36
  75. data/lib/action_view/renderer/renderer.rb +6 -4
  76. data/lib/action_view/renderer/streaming_template_renderer.rb +6 -5
  77. data/lib/action_view/renderer/template_renderer.rb +9 -4
  78. data/lib/action_view/rendering.rb +25 -7
  79. data/lib/action_view/ripper_ast_parser.rb +198 -0
  80. data/lib/action_view/routing_url_for.rb +8 -5
  81. data/lib/action_view/template/error.rb +122 -14
  82. data/lib/action_view/template/handlers/builder.rb +4 -4
  83. data/lib/action_view/template/handlers/erb/erubi.rb +23 -27
  84. data/lib/action_view/template/handlers/erb.rb +79 -1
  85. data/lib/action_view/template/handlers.rb +4 -4
  86. data/lib/action_view/template/html.rb +4 -4
  87. data/lib/action_view/template/inline.rb +3 -3
  88. data/lib/action_view/template/raw_file.rb +4 -4
  89. data/lib/action_view/template/renderable.rb +1 -1
  90. data/lib/action_view/template/resolver.rb +96 -313
  91. data/lib/action_view/template/text.rb +4 -4
  92. data/lib/action_view/template/types.rb +25 -32
  93. data/lib/action_view/template.rb +245 -41
  94. data/lib/action_view/template_details.rb +66 -0
  95. data/lib/action_view/template_path.rb +66 -0
  96. data/lib/action_view/test_case.rb +182 -23
  97. data/lib/action_view/testing/resolvers.rb +11 -12
  98. data/lib/action_view/unbound_template.rb +43 -7
  99. data/lib/action_view/version.rb +1 -1
  100. data/lib/action_view/view_paths.rb +19 -28
  101. data/lib/action_view.rb +6 -4
  102. data/lib/assets/compiled/rails-ujs.js +36 -5
  103. metadata +32 -25
@@ -2,9 +2,15 @@
2
2
 
3
3
  require "concurrent/map"
4
4
  require "action_view/path_set"
5
+ require "action_view/render_parser"
5
6
 
6
7
  module ActionView
7
8
  class DependencyTracker # :nodoc:
9
+ extend ActiveSupport::Autoload
10
+
11
+ autoload :ERBTracker
12
+ autoload :RipperTracker
13
+
8
14
  @trackers = Concurrent::Map.new
9
15
 
10
16
  def self.find_dependencies(name, template, view_paths = nil)
@@ -29,153 +35,6 @@ module ActionView
29
35
  @trackers.delete(handler)
30
36
  end
31
37
 
32
- class ERBTracker # :nodoc:
33
- EXPLICIT_DEPENDENCY = /# Template Dependency: (\S+)/
34
-
35
- # A valid ruby identifier - suitable for class, method and specially variable names
36
- IDENTIFIER = /
37
- [[:alpha:]_] # at least one uppercase letter, lowercase letter or underscore
38
- [[:word:]]* # followed by optional letters, numbers or underscores
39
- /x
40
-
41
- # Any kind of variable name. e.g. @instance, @@class, $global or local.
42
- # Possibly following a method call chain
43
- VARIABLE_OR_METHOD_CHAIN = /
44
- (?:\$|@{1,2})? # optional global, instance or class variable indicator
45
- (?:#{IDENTIFIER}\.)* # followed by an optional chain of zero-argument method calls
46
- (?<dynamic>#{IDENTIFIER}) # and a final valid identifier, captured as DYNAMIC
47
- /x
48
-
49
- # A simple string literal. e.g. "School's out!"
50
- STRING = /
51
- (?<quote>['"]) # an opening quote
52
- (?<static>.*?) # with anything inside, captured as STATIC
53
- \k<quote> # and a matching closing quote
54
- /x
55
-
56
- # Part of any hash containing the :partial key
57
- PARTIAL_HASH_KEY = /
58
- (?:\bpartial:|:partial\s*=>) # partial key in either old or new style hash syntax
59
- \s* # followed by optional spaces
60
- /x
61
-
62
- # Part of any hash containing the :layout key
63
- LAYOUT_HASH_KEY = /
64
- (?:\blayout:|:layout\s*=>) # layout key in either old or new style hash syntax
65
- \s* # followed by optional spaces
66
- /x
67
-
68
- # Matches:
69
- # partial: "comments/comment", collection: @all_comments => "comments/comment"
70
- # (object: @single_comment, partial: "comments/comment") => "comments/comment"
71
- #
72
- # "comments/comments"
73
- # 'comments/comments'
74
- # ('comments/comments')
75
- #
76
- # (@topic) => "topics/topic"
77
- # topics => "topics/topic"
78
- # (message.topics) => "topics/topic"
79
- RENDER_ARGUMENTS = /\A
80
- (?:\s*\(?\s*) # optional opening paren surrounded by spaces
81
- (?:.*?#{PARTIAL_HASH_KEY}|#{LAYOUT_HASH_KEY})? # optional hash, up to the partial or layout key declaration
82
- (?:#{STRING}|#{VARIABLE_OR_METHOD_CHAIN}) # finally, the dependency name of interest
83
- /xm
84
-
85
- LAYOUT_DEPENDENCY = /\A
86
- (?:\s*\(?\s*) # optional opening paren surrounded by spaces
87
- (?:.*?#{LAYOUT_HASH_KEY}) # check if the line has layout key declaration
88
- (?:#{STRING}|#{VARIABLE_OR_METHOD_CHAIN}) # finally, the dependency name of interest
89
- /xm
90
-
91
- def self.supports_view_paths? # :nodoc:
92
- true
93
- end
94
-
95
- def self.call(name, template, view_paths = nil)
96
- new(name, template, view_paths).dependencies
97
- end
98
-
99
- def initialize(name, template, view_paths = nil)
100
- @name, @template, @view_paths = name, template, view_paths
101
- end
102
-
103
- def dependencies
104
- render_dependencies + explicit_dependencies
105
- end
106
-
107
- attr_reader :name, :template
108
- private :name, :template
109
-
110
- private
111
- def source
112
- template.source
113
- end
114
-
115
- def directory
116
- name.split("/")[0..-2].join("/")
117
- end
118
-
119
- def render_dependencies
120
- render_dependencies = []
121
- render_calls = source.split(/\brender\b/).drop(1)
122
-
123
- render_calls.each do |arguments|
124
- add_dependencies(render_dependencies, arguments, LAYOUT_DEPENDENCY)
125
- add_dependencies(render_dependencies, arguments, RENDER_ARGUMENTS)
126
- end
127
-
128
- render_dependencies.uniq
129
- end
130
-
131
- def add_dependencies(render_dependencies, arguments, pattern)
132
- arguments.scan(pattern) do
133
- match = Regexp.last_match
134
- add_dynamic_dependency(render_dependencies, match[:dynamic])
135
- add_static_dependency(render_dependencies, match[:static], match[:quote])
136
- end
137
- end
138
-
139
- def add_dynamic_dependency(dependencies, dependency)
140
- if dependency
141
- dependencies << "#{dependency.pluralize}/#{dependency.singularize}"
142
- end
143
- end
144
-
145
- def add_static_dependency(dependencies, dependency, quote_type)
146
- if quote_type == '"'
147
- # Ignore if there is interpolation
148
- return if dependency.include?('#{')
149
- end
150
-
151
- if dependency
152
- if dependency.include?("/")
153
- dependencies << dependency
154
- else
155
- dependencies << "#{directory}/#{dependency}"
156
- end
157
- end
158
- end
159
-
160
- def resolve_directories(wildcard_dependencies)
161
- return [] unless @view_paths
162
-
163
- wildcard_dependencies.flat_map { |query, templates|
164
- @view_paths.find_all_with_query(query).map do |template|
165
- "#{File.dirname(query)}/#{File.basename(template).split('.').first}"
166
- end
167
- }.sort
168
- end
169
-
170
- def explicit_dependencies
171
- dependencies = source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
172
-
173
- wildcards, explicits = dependencies.partition { |dependency| dependency.end_with?("*") }
174
-
175
- (explicits + resolve_directories(wildcards)).uniq
176
- end
177
- end
178
-
179
38
  register_tracker :erb, ERBTracker
180
39
  end
181
40
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ def self.deprecator # :nodoc:
5
+ @deprecator ||= ActiveSupport::Deprecation.new
6
+ end
7
+ end
@@ -11,21 +11,22 @@ module ActionView
11
11
  #
12
12
  # * <tt>name</tt> - Template name
13
13
  # * <tt>format</tt> - Template format
14
- # * <tt>finder</tt> - An instance of <tt>ActionView::LookupContext</tt>
14
+ # * +finder+ - An instance of ActionView::LookupContext
15
15
  # * <tt>dependencies</tt> - An array of dependent views
16
16
  def digest(name:, format: nil, finder:, dependencies: nil)
17
17
  if dependencies.nil? || dependencies.empty?
18
18
  cache_key = "#{name}.#{format}"
19
19
  else
20
- cache_key = [ name, format, dependencies ].flatten.compact.join(".")
20
+ dependencies_suffix = dependencies.flatten.tap(&:compact!).join(".")
21
+ cache_key = "#{name}.#{format}.#{dependencies_suffix}"
21
22
  end
22
23
 
23
24
  # this is a correctly done double-checked locking idiom
24
25
  # (Concurrent::Map's lookups have volatile semantics)
25
26
  finder.digest_cache[cache_key] || @@digest_mutex.synchronize do
26
27
  finder.digest_cache.fetch(cache_key) do # re-check under lock
27
- partial = name.include?("/_")
28
- root = tree(name, finder, partial)
28
+ path = TemplatePath.parse(name)
29
+ root = tree(path.to_s, finder, path.partial?)
29
30
  dependencies.each do |injected_dep|
30
31
  root.children << Injected.new(injected_dep, nil, nil)
31
32
  end if dependencies
@@ -43,7 +44,9 @@ module ActionView
43
44
  logical_name = name.gsub(%r|/_|, "/")
44
45
  interpolated = name.include?("#")
45
46
 
46
- if !interpolated && (template = find_template(finder, logical_name, [], partial, []))
47
+ path = TemplatePath.parse(name)
48
+
49
+ if !interpolated && (template = find_template(finder, path.name, [path.prefix], partial, []))
47
50
  if node = seen[template.identifier] # handle cycles in the tree
48
51
  node
49
52
  else
@@ -3,7 +3,7 @@
3
3
  require "active_support/core_ext/string/output_safety"
4
4
 
5
5
  module ActionView
6
- class OutputFlow #:nodoc:
6
+ class OutputFlow # :nodoc:
7
7
  attr_reader :content
8
8
 
9
9
  def initialize
@@ -17,17 +17,17 @@ module ActionView
17
17
 
18
18
  # Called by each renderer object to set the layout contents.
19
19
  def set(key, value)
20
- @content[key] = ActiveSupport::SafeBuffer.new(value)
20
+ @content[key] = ActiveSupport::SafeBuffer.new(value.to_s)
21
21
  end
22
22
 
23
23
  # Called by content_for
24
24
  def append(key, value)
25
- @content[key] << value
25
+ @content[key] << value.to_s
26
26
  end
27
27
  alias_method :append!, :append
28
28
  end
29
29
 
30
- class StreamingFlow < OutputFlow #:nodoc:
30
+ class StreamingFlow < OutputFlow # :nodoc:
31
31
  def initialize(view, fiber)
32
32
  @view = view
33
33
  @parent = nil
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionView
4
- # Returns the version of the currently loaded Action View as a <tt>Gem::Version</tt>
4
+ # Returns the currently loaded version of Action View as a +Gem::Version+.
5
5
  def self.gem_version
6
6
  Gem::Version.new VERSION::STRING
7
7
  end
8
8
 
9
9
  module VERSION
10
- MAJOR = 6
10
+ MAJOR = 7
11
11
  MINOR = 1
12
- TINY = 7
13
- PRE = "2"
12
+ TINY = 3
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -4,11 +4,11 @@ require "active_support/core_ext/module/attribute_accessors"
4
4
  require "active_support/core_ext/enumerable"
5
5
 
6
6
  module ActionView
7
- # = Active Model Helpers
8
- module Helpers #:nodoc:
7
+ module Helpers # :nodoc:
9
8
  module ActiveModelHelper
10
9
  end
11
10
 
11
+ # = Active \Model Instance Tag \Helpers
12
12
  module ActiveModelInstanceTag
13
13
  def object
14
14
  @active_model_object ||= begin
@@ -27,7 +27,7 @@ module ActionView
27
27
 
28
28
  def error_wrapping(html_tag)
29
29
  if object_has_errors?
30
- Base.field_error_proc.call(html_tag, self)
30
+ @template_object.instance_exec(html_tag, self, &Base.field_error_proc)
31
31
  else
32
32
  html_tag
33
33
  end