actionview 7.2.3 → 8.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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +112 -121
  3. data/lib/action_view/base.rb +5 -2
  4. data/lib/action_view/buffers.rb +1 -1
  5. data/lib/action_view/dependency_tracker/erb_tracker.rb +37 -28
  6. data/lib/action_view/dependency_tracker/ruby_tracker.rb +2 -19
  7. data/lib/action_view/dependency_tracker/wildcard_resolver.rb +32 -0
  8. data/lib/action_view/dependency_tracker.rb +7 -1
  9. data/lib/action_view/gem_version.rb +2 -2
  10. data/lib/action_view/helpers/asset_tag_helper.rb +21 -2
  11. data/lib/action_view/helpers/atom_feed_helper.rb +0 -2
  12. data/lib/action_view/helpers/cache_helper.rb +8 -0
  13. data/lib/action_view/helpers/capture_helper.rb +2 -2
  14. data/lib/action_view/helpers/controller_helper.rb +6 -2
  15. data/lib/action_view/helpers/date_helper.rb +20 -3
  16. data/lib/action_view/helpers/form_helper.rb +76 -76
  17. data/lib/action_view/helpers/form_options_helper.rb +33 -32
  18. data/lib/action_view/helpers/form_tag_helper.rb +35 -25
  19. data/lib/action_view/helpers/javascript_helper.rb +5 -1
  20. data/lib/action_view/helpers/number_helper.rb +14 -0
  21. data/lib/action_view/helpers/rendering_helper.rb +160 -50
  22. data/lib/action_view/helpers/sanitize_helper.rb +6 -0
  23. data/lib/action_view/helpers/tag_helper.rb +62 -75
  24. data/lib/action_view/helpers/tags/base.rb +11 -9
  25. data/lib/action_view/helpers/tags/check_box.rb +9 -3
  26. data/lib/action_view/helpers/tags/collection_check_boxes.rb +4 -3
  27. data/lib/action_view/helpers/tags/datetime_field.rb +1 -1
  28. data/lib/action_view/helpers/tags/file_field.rb +7 -2
  29. data/lib/action_view/helpers/tags/hidden_field.rb +1 -1
  30. data/lib/action_view/helpers/tags/label.rb +3 -10
  31. data/lib/action_view/helpers/tags/radio_button.rb +1 -1
  32. data/lib/action_view/helpers/tags/select.rb +6 -1
  33. data/lib/action_view/helpers/tags/select_renderer.rb +6 -4
  34. data/lib/action_view/helpers/tags/text_area.rb +1 -1
  35. data/lib/action_view/helpers/tags/text_field.rb +1 -1
  36. data/lib/action_view/helpers/translation_helper.rb +6 -1
  37. data/lib/action_view/helpers/url_helper.rb +39 -13
  38. data/lib/action_view/layouts.rb +1 -1
  39. data/lib/action_view/locale/en.yml +3 -0
  40. data/lib/action_view/log_subscriber.rb +1 -4
  41. data/lib/action_view/railtie.rb +12 -1
  42. data/lib/action_view/record_identifier.rb +22 -1
  43. data/lib/action_view/render_parser/prism_render_parser.rb +13 -1
  44. data/lib/action_view/render_parser/ripper_render_parser.rb +10 -1
  45. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +5 -1
  46. data/lib/action_view/renderer/partial_renderer.rb +16 -0
  47. data/lib/action_view/renderer/streaming_template_renderer.rb +8 -2
  48. data/lib/action_view/rendering.rb +2 -3
  49. data/lib/action_view/structured_event_subscriber.rb +97 -0
  50. data/lib/action_view/template/error.rb +7 -3
  51. data/lib/action_view/template/handlers/erb/erubi.rb +1 -1
  52. data/lib/action_view/template/handlers/erb.rb +37 -12
  53. data/lib/action_view/template/raw_file.rb +4 -0
  54. data/lib/action_view/template/resolver.rb +0 -1
  55. data/lib/action_view/template.rb +9 -4
  56. data/lib/action_view/test_case.rb +50 -52
  57. data/lib/action_view.rb +3 -0
  58. metadata +14 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 773338461dd6a54e8b6efa075c2be80d8f8c975ee46bd2167bc7e2fcd8e78f35
4
- data.tar.gz: 22244120a030dfc49034d8d790fa86013b1de42b5ee7acbe75243580c9eec7c1
3
+ metadata.gz: 96267f5fb9e3f51b3f9532cf10d78e0454480729b75a758b6df1bf6bb903384f
4
+ data.tar.gz: f7befef7e6c94a2dda6868cd265cbb4009576883d881a9f28195d68649b9511c
5
5
  SHA512:
6
- metadata.gz: 1c26e2052e3f599c7f28c19892948c6b3f8cdeef005a4dc54762b4e74309ac32ef794115b0e46d2364624b26debb85a6aaebc938813d08e69e9c670c3bf79ae6
7
- data.tar.gz: 15bdc1f27280a327a1270ddf794b484d68f88af959c2d49361ef0e33c37e547b81166c8b92ef400f7e9a62c8192820bd58042733335ff4a9c3f1a77b660f775f
6
+ metadata.gz: bd4eb208e63b468bd0b97bda5b8202a7954e6545e05b6a600fcd0a1d703303e99ff2ffbd929ec63142e118267a61cc1cd7f62f5deed6b47ed05e1e6bed50291b
7
+ data.tar.gz: 98fcb31d4441433ac6bd216aec193446d4e06c6116e038bf8d6c5166275937b8301879c3b2d454a1cf86fe9ed6a373898d7f808b35ef4881885231762dcba5b4
data/CHANGELOG.md CHANGED
@@ -1,200 +1,191 @@
1
- ## Rails 7.2.3 (October 28, 2025) ##
1
+ ## Rails 8.1.3 (March 24, 2026) ##
2
2
 
3
- * Fix `javascript_include_tag` `type` option to accept either strings and symbols.
3
+ * Fix encoding errors for string locals containing non-ASCII characters.
4
4
 
5
- ```ruby
6
- javascript_include_tag "application", type: :module
7
- javascript_include_tag "application", type: "module"
8
- ```
9
-
10
- Previously, only the string value was recoginized.
11
-
12
- *Jean Boussier*
13
-
14
- * Fix `excerpt` helper with non-whitespace separator.
15
-
16
- *Jonathan Hefner*
17
-
18
- * Respect `html_options[:form]` when `collection_checkboxes` generates the
19
- hidden `<input>`.
20
-
21
- *Riccardo Odone*
5
+ *Kataoka Katsuki*
22
6
 
23
- * Layouts have access to local variables passed to `render`.
7
+ * Fix collection caching to only forward `expires_in` argument if explicitly set.
24
8
 
25
- This fixes #31680 which was a regression in Rails 5.1.
9
+ *Pieter Visser*
26
10
 
27
- *Mike Dalessio*
11
+ ## Rails 8.1.2.1 (March 23, 2026) ##
28
12
 
29
- * Argument errors related to strict locals in templates now raise an
30
- `ActionView::StrictLocalsError`, and all other argument errors are reraised as-is.
13
+ * Fix possible XSS in DebugExceptions middleware
31
14
 
32
- Previously, any `ArgumentError` raised during template rendering was swallowed during strict
33
- local error handling, so that an `ArgumentError` unrelated to strict locals (e.g., a helper
34
- method invoked with incorrect arguments) would be replaced by a similar `ArgumentError` with an
35
- unrelated backtrace, making it difficult to debug templates.
15
+ [CVE-2026-33167]
36
16
 
37
- Now, any `ArgumentError` unrelated to strict locals is reraised, preserving the original
38
- backtrace for developers.
17
+ *John Hawthorn*
39
18
 
40
- Also note that `ActionView::StrictLocalsError` is a subclass of `ArgumentError`, so any existing
41
- code that rescues `ArgumentError` will continue to work.
19
+ * Skip blank attribute names in tag helpers to avoid generating invalid HTML.
42
20
 
43
- Fixes #52227.
21
+ [CVE-2026-33168]
44
22
 
45
23
  *Mike Dalessio*
46
24
 
47
- * Fix stack overflow error in dependency tracker when dealing with circular dependencies
48
-
49
- *Jean Boussier*
50
-
51
- * Fix a crash in ERB template error highlighting when the error occurs on a
52
- line in the compiled template that is past the end of the source template.
53
-
54
- *Martin Emde*
55
-
56
- * Improve reliability of ERB template error highlighting.
57
- Fix infinite loops and crashes in highlighting and
58
- improve tolerance for alternate ERB handlers.
59
-
60
- *Martin Emde*
61
25
 
26
+ ## Rails 8.1.2 (January 08, 2026) ##
62
27
 
63
- ## Rails 7.2.2.2 (August 13, 2025) ##
28
+ * Fix `file_field` to join mime types with a comma when provided as Array
64
29
 
65
- * No changes.
30
+ ```ruby
31
+ file_field(:article, :image, accept: ['image/png', 'image/gif', 'image/jpeg'])
32
+ ```
66
33
 
34
+ Now behaves likes:
67
35
 
68
- ## Rails 7.2.2.1 (December 10, 2024) ##
36
+ ```
37
+ file_field(:article, :image, accept: 'image/png,image/gif,image/jpeg')
38
+ ```
69
39
 
70
- * No changes.
40
+ *Bogdan Gusiev*
71
41
 
42
+ * Fix strict locals parsing to handle multiline definitions.
72
43
 
73
- ## Rails 7.2.2 (October 30, 2024) ##
44
+ *Said Kaldybaev*
74
45
 
75
- * No changes.
46
+ * Fix `content_security_policy_nonce` error in mailers when using `content_security_policy_nonce_auto` setting.
76
47
 
48
+ The `content_security_policy_nonce helper` is provided by `ActionController::ContentSecurityPolicy`, and it relies on `request.content_security_policy_nonc`e. Mailers lack both the module and the request object.
77
49
 
78
- ## Rails 7.2.1.2 (October 23, 2024) ##
50
+ *Jarrett Lusso*
79
51
 
80
- * No changes.
81
52
 
53
+ ## Rails 8.1.1 (October 28, 2025) ##
82
54
 
83
- ## Rails 7.2.1.1 (October 15, 2024) ##
55
+ * Respect `remove_hidden_field_autocomplete` config in form builder `hidden_field`.
84
56
 
85
- * No changes.
57
+ *Rafael Mendonça França*
86
58
 
87
59
 
88
- ## Rails 7.2.1 (August 22, 2024) ##
60
+ ## Rails 8.1.0 (October 22, 2025) ##
89
61
 
90
- * No changes.
62
+ * The BEGIN template annotation/comment was previously printed on the same line as the following element. We now insert a newline inside the comment so it spans two lines without adding visible whitespace to the HTML output to enhance readability.
91
63
 
64
+ Before:
65
+ ```
66
+ <!-- BEGIN /Users/siaw23/Desktop/rails/actionview/test/fixtures/actionpack/test/greeting.html.erb --><p>This is grand!</p>
67
+ ```
92
68
 
93
- ## Rails 7.2.0 (August 09, 2024) ##
69
+ After:
70
+ ```
71
+ <!-- BEGIN /Users/siaw23/Desktop/rails/actionview/test/fixtures/actionpack/test/greeting.html.erb
72
+ --><p>This is grand!</p>
73
+ ```
74
+ *Emmanuel Hayford*
94
75
 
95
- * Fix templates with strict locals to also include `local_assigns`.
76
+ * Add structured events for Action View:
77
+ - `action_view.render_template`
78
+ - `action_view.render_partial`
79
+ - `action_view.render_layout`
80
+ - `action_view.render_collection`
81
+ - `action_view.render_start`
96
82
 
97
- Previously templates defining strict locals wouldn't receive the `local_assigns`
98
- hash.
83
+ *Gannon McGibbon*
99
84
 
100
- *Jean Boussier*
85
+ * Fix label with `for` option not getting prefixed by form `namespace` value
101
86
 
102
- * Add queries count to template rendering instrumentation.
87
+ *Abeid Ahmed*, *Hartley McGuire*
103
88
 
104
- ```
105
- # Before
106
- Completed 200 OK in 3804ms (Views: 41.0ms | ActiveRecord: 33.5ms | Allocations: 112788)
89
+ * Add `fetchpriority` to Link headers to match HTML generated by `preload_link_tag`.
107
90
 
108
- # After
109
- Completed 200 OK in 3804ms (Views: 41.0ms | ActiveRecord: 33.5ms (2 queries, 1 cached) | Allocations: 112788)
110
- ```
91
+ *Guillermo Iguaran*
111
92
 
112
- *fatkodima*
93
+ * Add CSP `nonce` to Link headers generated by `preload_link_tag`.
113
94
 
114
- * Raise `ArgumentError` if `:renderable` object does not respond to `#render_in`.
95
+ *Alexander Gitter*
115
96
 
116
- *Sean Doyle*
97
+ * Allow `current_page?` to match against specific HTTP method(s) with a `method:` option.
117
98
 
118
- * Add the `nonce: true` option for `stylesheet_link_tag` helper to support automatic nonce generation for Content Security Policy.
99
+ *Ben Sheldon*
119
100
 
120
- Works the same way as `javascript_include_tag nonce: true` does.
101
+ * Remove `autocomplete="off"` on hidden inputs generated by the following
102
+ tags:
121
103
 
122
- *Akhil G Krishnan*, *AJ Esler*
104
+ * `form_tag`, `token_tag`, `method_tag`
123
105
 
124
- * Parse `ActionView::TestCase#rendered` HTML content as `Nokogiri::XML::DocumentFragment` instead of `Nokogiri::XML::Document`.
106
+ As well as the hidden parameter fields included in `button_to`,
107
+ `check_box`, `select` (with `multiple`) and `file_field` forms.
125
108
 
126
- *Sean Doyle*
109
+ *nkulway*
127
110
 
128
- * Rename `ActionView::TestCase::Behavior::Content` to `ActionView::TestCase::Behavior::RenderedViewContent`.
111
+ * Enable configuring the strategy for tracking dependencies between Action
112
+ View templates.
129
113
 
130
- Make `RenderedViewContent` inherit from `String`. Make private API with `:nodoc:`
114
+ The existing `:regex` strategy is kept as the default, but with
115
+ `load_defaults 8.1` the strategy will be `:ruby` (using a real Ruby parser).
131
116
 
132
- *Sean Doyle*
117
+ *Hartley McGuire*
133
118
 
134
- * Deprecate passing `nil` as value for the `model:` argument to the `form_with` method.
119
+ * Introduce `relative_time_in_words` helper
135
120
 
136
- *Collin Jilbert*
121
+ ```ruby
122
+ relative_time_in_words(3.minutes.from_now) # => "in 3 minutes"
123
+ relative_time_in_words(3.minutes.ago) # => "3 minutes ago"
124
+ relative_time_in_words(10.seconds.ago, include_seconds: true) # => "less than 10 seconds ago"
125
+ ```
137
126
 
138
- * Alias `field_set_tag` helper to `fieldset_tag` to match `<fieldset>` element.
127
+ *Matheus Richard*
139
128
 
140
- *Sean Doyle*
129
+ * Make `nonce: false` remove the nonce attribute from `javascript_tag`, `javascript_include_tag`, and `stylesheet_link_tag`.
141
130
 
142
- * Deprecate passing content to void elements when using `tag.br` type tag builders.
131
+ *francktrouillez*
143
132
 
144
- *Hartley McGuire*
133
+ * Add `dom_target` helper to create `dom_id`-like strings from an unlimited
134
+ number of objects.
145
135
 
146
- * Fix the `number_to_human_size` view helper to correctly work with negative numbers.
136
+ *Ben Sheldon*
147
137
 
148
- *Earlopain*
138
+ * Respect `html_options[:form]` when `collection_checkboxes` generates the
139
+ hidden `<input>`.
149
140
 
150
- * Automatically discard the implicit locals injected by collection rendering for template that can't accept them.
141
+ *Riccardo Odone*
151
142
 
152
- When rendering a collection, two implicit variables are injected, which breaks templates with strict locals.
143
+ * Layouts have access to local variables passed to `render`.
153
144
 
154
- Now they are only passed if the template will actually accept them.
145
+ This fixes #31680 which was a regression in Rails 5.1.
155
146
 
156
- *Yasha Krasnou*, *Jean Boussier*
147
+ *Mike Dalessio*
157
148
 
158
- * Fix `@rails/ujs` calling `start()` an extra time when using bundlers.
149
+ * Argument errors related to strict locals in templates now raise an
150
+ `ActionView::StrictLocalsError`, and all other argument errors are reraised as-is.
159
151
 
160
- *Hartley McGuire*, *Ryunosuke Sato*
152
+ Previously, any `ArgumentError` raised during template rendering was swallowed during strict
153
+ local error handling, so that an `ArgumentError` unrelated to strict locals (e.g., a helper
154
+ method invoked with incorrect arguments) would be replaced by a similar `ArgumentError` with an
155
+ unrelated backtrace, making it difficult to debug templates.
161
156
 
162
- * Fix the `capture` view helper compatibility with HAML and Slim.
157
+ Now, any `ArgumentError` unrelated to strict locals is reraised, preserving the original
158
+ backtrace for developers.
163
159
 
164
- When a blank string was captured in HAML or Slim (and possibly other template engines)
165
- it would instead return the entire buffer.
160
+ Also note that `ActionView::StrictLocalsError` is a subclass of `ArgumentError`, so any existing
161
+ code that rescues `ArgumentError` will continue to work.
166
162
 
167
- *Jean Boussier*
163
+ Fixes #52227.
168
164
 
169
- * Updated `@rails/ujs` files to ignore certain data-* attributes when element is contenteditable.
165
+ *Mike Dalessio*
170
166
 
171
- This fix was already landed in >= 7.0.4.3, < 7.1.0.
172
- [[CVE-2023-23913](https://github.com/advisories/GHSA-xp5h-f8jf-rc8q)]
167
+ * Improve error highlighting of multi-line methods in ERB templates or
168
+ templates where the error occurs within a do-end block.
173
169
 
174
- *Ryunosuke Sato*
170
+ *Martin Emde*
175
171
 
176
- * Added validation for HTML tag names in the `tag` and `content_tag` helper method.
172
+ * Fix a crash in ERB template error highlighting when the error occurs on a
173
+ line in the compiled template that is past the end of the source template.
177
174
 
178
- The `tag` and `content_tag` method now checks that the provided tag name adheres to the HTML
179
- specification. If an invalid HTML tag name is provided, the method raises an `ArgumentError`
180
- with an appropriate error message.
175
+ *Martin Emde*
181
176
 
182
- Examples:
177
+ * Improve reliability of ERB template error highlighting.
178
+ Fix infinite loops and crashes in highlighting and
179
+ improve tolerance for alternate ERB handlers.
183
180
 
184
- ```ruby
185
- # Raises ArgumentError: Invalid HTML5 tag name: 12p
186
- content_tag("12p") # Starting with a number
181
+ *Martin Emde*
187
182
 
188
- # Raises ArgumentError: Invalid HTML5 tag name: ""
189
- content_tag("") # Empty tag name
183
+ * Allow `hidden_field` and `hidden_field_tag` to accept a custom autocomplete value.
190
184
 
191
- # Raises ArgumentError: Invalid HTML5 tag name: div/
192
- tag("div/") # Contains a solidus
185
+ *brendon*
193
186
 
194
- # Raises ArgumentError: Invalid HTML5 tag name: "image file"
195
- tag("image file") # Contains a space
196
- ```
187
+ * Add a new configuration `content_security_policy_nonce_auto` for automatically adding a nonce to the tags affected by the directives specified by the `content_security_policy_nonce_directives` configuration option.
197
188
 
198
- *Akhil G Krishnan*
189
+ *francktrouillez*
199
190
 
200
- Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/actionview/CHANGELOG.md) for previous changes.
191
+ Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/actionview/CHANGELOG.md) for previous changes.
@@ -4,6 +4,7 @@ require "active_support/core_ext/module/attr_internal"
4
4
  require "active_support/core_ext/module/attribute_accessors"
5
5
  require "active_support/ordered_options"
6
6
  require "action_view/log_subscriber"
7
+ require "action_view/structured_event_subscriber"
7
8
  require "action_view/helpers"
8
9
  require "action_view/context"
9
10
  require "action_view/template"
@@ -181,6 +182,10 @@ module ActionView # :nodoc:
181
182
  class_attribute :_routes
182
183
  class_attribute :logger
183
184
 
185
+ # Specify whether to omit autocomplete="off" on hidden inputs generated by helpers.
186
+ # Configured via `config.action_view.remove_hidden_field_autocomplete`
187
+ cattr_accessor :remove_hidden_field_autocomplete, default: false
188
+
184
189
  class << self
185
190
  delegate :erb_trim_mode=, to: "ActionView::Template::Handlers::ERB"
186
191
 
@@ -242,8 +247,6 @@ module ActionView # :nodoc:
242
247
  # :startdoc:
243
248
 
244
249
  def initialize(lookup_context, assigns, controller) # :nodoc:
245
- @_config = ActiveSupport::InheritableOptions.new
246
-
247
250
  @lookup_context = lookup_context
248
251
 
249
252
  @view_renderer = ActionView::Renderer.new @lookup_context
@@ -45,7 +45,7 @@ module ActionView
45
45
  @raw_buffer << if value.html_safe?
46
46
  value
47
47
  else
48
- CGI.escapeHTML(value)
48
+ ERB::Util.unwrapped_html_escape(value)
49
49
  end
50
50
  end
51
51
  self
@@ -74,7 +74,7 @@ module ActionView
74
74
  end
75
75
 
76
76
  def dependencies
77
- render_dependencies + explicit_dependencies
77
+ WildcardResolver.new(@view_paths, render_dependencies + explicit_dependencies).resolve
78
78
  end
79
79
 
80
80
  attr_reader :name, :template
@@ -90,15 +90,15 @@ module ActionView
90
90
  end
91
91
 
92
92
  def render_dependencies
93
- render_dependencies = []
94
- render_calls = source.split(/\brender\b/).drop(1)
93
+ dependencies = []
94
+ render_calls = source.scan(/<%(?:(?:(?!<%).)*?\brender\b((?:(?!%>).)*?))%>/m).flatten
95
95
 
96
96
  render_calls.each do |arguments|
97
- add_dependencies(render_dependencies, arguments, LAYOUT_DEPENDENCY)
98
- add_dependencies(render_dependencies, arguments, RENDER_ARGUMENTS)
97
+ add_dependencies(dependencies, arguments, LAYOUT_DEPENDENCY)
98
+ add_dependencies(dependencies, arguments, RENDER_ARGUMENTS)
99
99
  end
100
100
 
101
- render_dependencies.uniq
101
+ dependencies
102
102
  end
103
103
 
104
104
  def add_dependencies(render_dependencies, arguments, pattern)
@@ -116,12 +116,37 @@ module ActionView
116
116
  end
117
117
 
118
118
  def add_static_dependency(dependencies, dependency, quote_type)
119
- if quote_type == '"'
120
- # Ignore if there is interpolation
121
- return if dependency.include?('#{')
122
- end
119
+ if quote_type == '"' && dependency.include?('#{')
120
+ scanner = StringScanner.new(dependency)
121
+
122
+ wildcard_dependency = +""
123
+
124
+ while !scanner.eos?
125
+ if scanner.scan_until(/\#{/)
126
+ unmatched_brackets = 1
127
+ wildcard_dependency << scanner.pre_match
128
+
129
+ while unmatched_brackets > 0 && !scanner.eos?
130
+ found = scanner.scan_until(/[{}]/)
131
+ return unless found
132
+
133
+ case scanner.matched
134
+ when "{"
135
+ unmatched_brackets += 1
136
+ when "}"
137
+ unmatched_brackets -= 1
138
+ end
139
+ end
140
+
141
+ wildcard_dependency << "*"
142
+ else
143
+ wildcard_dependency << scanner.rest
144
+ scanner.terminate
145
+ end
146
+ end
123
147
 
124
- if dependency
148
+ dependencies << wildcard_dependency
149
+ elsif dependency
125
150
  if dependency.include?("/")
126
151
  dependencies << dependency
127
152
  else
@@ -130,24 +155,8 @@ module ActionView
130
155
  end
131
156
  end
132
157
 
133
- def resolve_directories(wildcard_dependencies)
134
- return [] unless @view_paths
135
- return [] if wildcard_dependencies.empty?
136
-
137
- # Remove trailing "/*"
138
- prefixes = wildcard_dependencies.map { |query| query[0..-3] }
139
-
140
- @view_paths.flat_map(&:all_template_paths).uniq.filter_map { |path|
141
- path.to_s if prefixes.include?(path.prefix)
142
- }.sort
143
- end
144
-
145
158
  def explicit_dependencies
146
- dependencies = source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
147
-
148
- wildcards, explicits = dependencies.partition { |dependency| dependency.end_with?("/*") }
149
-
150
- (explicits + resolve_directories(wildcards)).uniq
159
+ source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
151
160
  end
152
161
  end
153
162
  end
@@ -10,7 +10,7 @@ module ActionView
10
10
  end
11
11
 
12
12
  def dependencies
13
- render_dependencies + explicit_dependencies
13
+ WildcardResolver.new(view_paths, render_dependencies + explicit_dependencies).resolve
14
14
  end
15
15
 
16
16
  def self.supports_view_paths? # :nodoc:
@@ -31,29 +31,12 @@ module ActionView
31
31
  compiled_source = template.handler.call(template, template.source)
32
32
 
33
33
  @parser_class.new(@name, compiled_source).render_calls.filter_map do |render_call|
34
- next if render_call.end_with?("/_")
35
34
  render_call.gsub(%r|/_|, "/")
36
35
  end
37
36
  end
38
37
 
39
38
  def explicit_dependencies
40
- dependencies = template.source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
41
-
42
- wildcards, explicits = dependencies.partition { |dependency| dependency.end_with?("/*") }
43
-
44
- (explicits + resolve_directories(wildcards)).uniq
45
- end
46
-
47
- def resolve_directories(wildcard_dependencies)
48
- return [] unless view_paths
49
- return [] if wildcard_dependencies.empty?
50
-
51
- # Remove trailing "/*"
52
- prefixes = wildcard_dependencies.map { |query| query[0..-3] }
53
-
54
- view_paths.flat_map(&:all_template_paths).uniq.filter_map { |path|
55
- path.to_s if prefixes.include?(path.prefix)
56
- }.sort
39
+ template.source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
57
40
  end
58
41
  end
59
42
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ class DependencyTracker # :nodoc:
5
+ class WildcardResolver # :nodoc:
6
+ def initialize(view_paths, dependencies)
7
+ @view_paths = view_paths
8
+
9
+ @wildcard_dependencies, @explicit_dependencies =
10
+ dependencies.partition { |dependency| dependency.end_with?("/*") }
11
+ end
12
+
13
+ def resolve
14
+ return explicit_dependencies.uniq if !view_paths || wildcard_dependencies.empty?
15
+
16
+ (explicit_dependencies + resolved_wildcard_dependencies).uniq
17
+ end
18
+
19
+ private
20
+ attr_reader :explicit_dependencies, :wildcard_dependencies, :view_paths
21
+
22
+ def resolved_wildcard_dependencies
23
+ # Remove trailing "/*"
24
+ prefixes = wildcard_dependencies.map { |query| query[0..-3] }
25
+
26
+ view_paths.flat_map(&:all_template_paths).uniq.filter_map { |path|
27
+ path.to_s if prefixes.include?(path.prefix)
28
+ }.sort
29
+ end
30
+ end
31
+ end
32
+ end
@@ -10,6 +10,7 @@ module ActionView
10
10
 
11
11
  autoload :ERBTracker
12
12
  autoload :RubyTracker
13
+ autoload :WildcardResolver
13
14
 
14
15
  @trackers = Concurrent::Map.new
15
16
 
@@ -35,6 +36,11 @@ module ActionView
35
36
  @trackers.delete(handler)
36
37
  end
37
38
 
38
- register_tracker :erb, ERBTracker
39
+ case ActionView.render_tracker
40
+ when :ruby
41
+ register_tracker :erb, RubyTracker
42
+ else
43
+ register_tracker :erb, ERBTracker
44
+ end
39
45
  end
40
46
  end
@@ -7,8 +7,8 @@ module ActionView
7
7
  end
8
8
 
9
9
  module VERSION
10
- MAJOR = 7
11
- MINOR = 2
10
+ MAJOR = 8
11
+ MINOR = 1
12
12
  TINY = 3
13
13
  PRE = nil
14
14
 
@@ -26,6 +26,8 @@ module ActionView
26
26
  mattr_accessor :image_decoding
27
27
  mattr_accessor :preload_links_header
28
28
  mattr_accessor :apply_stylesheet_media_default
29
+ mattr_accessor :auto_include_nonce_for_scripts
30
+ mattr_accessor :auto_include_nonce_for_styles
29
31
 
30
32
  # Returns an HTML script tag for each of the +sources+ provided.
31
33
  #
@@ -127,6 +129,7 @@ module ActionView
127
129
  preload_link = "<#{href}>; rel=#{rel}; as=script"
128
130
  preload_link += "; crossorigin=#{crossorigin}" unless crossorigin.nil?
129
131
  preload_link += "; integrity=#{integrity}" unless integrity.nil?
132
+ preload_link += "; nonce=#{content_security_policy_nonce}" if options["nonce"] == true
130
133
  preload_link += "; nopush" if nopush
131
134
  preload_links << preload_link
132
135
  end
@@ -134,8 +137,10 @@ module ActionView
134
137
  "src" => href,
135
138
  "crossorigin" => crossorigin
136
139
  }.merge!(options)
137
- if tag_options["nonce"] == true
140
+ if tag_options["nonce"] == true || (!tag_options.key?("nonce") && auto_include_nonce_for_scripts)
138
141
  tag_options["nonce"] = content_security_policy_nonce
142
+ elsif tag_options["nonce"] == false
143
+ tag_options.delete("nonce")
139
144
  end
140
145
  content_tag("script", "", tag_options)
141
146
  }.join("\n").html_safe
@@ -215,6 +220,7 @@ module ActionView
215
220
  preload_link = "<#{href}>; rel=preload; as=style"
216
221
  preload_link += "; crossorigin=#{crossorigin}" unless crossorigin.nil?
217
222
  preload_link += "; integrity=#{integrity}" unless integrity.nil?
223
+ preload_link += "; nonce=#{content_security_policy_nonce}" if options["nonce"] == true
218
224
  preload_link += "; nopush" if nopush
219
225
  preload_links << preload_link
220
226
  end
@@ -223,8 +229,10 @@ module ActionView
223
229
  "crossorigin" => crossorigin,
224
230
  "href" => href
225
231
  }.merge!(options)
226
- if tag_options["nonce"] == true
232
+ if tag_options["nonce"] == true || (!tag_options.key?("nonce") && auto_include_nonce_for_styles && respond_to?(:content_security_policy_nonce))
227
233
  tag_options["nonce"] = content_security_policy_nonce
234
+ elsif tag_options["nonce"] == false
235
+ tag_options.delete("nonce")
228
236
  end
229
237
 
230
238
  if apply_stylesheet_media_default && tag_options["media"].blank?
@@ -360,8 +368,16 @@ module ActionView
360
368
  crossorigin = options.delete(:crossorigin)
361
369
  crossorigin = "anonymous" if crossorigin == true || (crossorigin.blank? && as_type == "font")
362
370
  integrity = options[:integrity]
371
+ fetchpriority = options.delete(:fetchpriority)
363
372
  nopush = options.delete(:nopush) || false
364
373
  rel = mime_type == "module" || mime_type == :module ? "modulepreload" : "preload"
374
+ add_nonce = content_security_policy_nonce &&
375
+ respond_to?(:request) &&
376
+ request.content_security_policy_nonce_directives&.include?("#{as_type}-src")
377
+
378
+ if add_nonce
379
+ options[:nonce] = content_security_policy_nonce
380
+ end
365
381
 
366
382
  link_tag = tag.link(
367
383
  rel: rel,
@@ -369,12 +385,15 @@ module ActionView
369
385
  as: as_type,
370
386
  type: mime_type,
371
387
  crossorigin: crossorigin,
388
+ fetchpriority: fetchpriority,
372
389
  **options.symbolize_keys)
373
390
 
374
391
  preload_link = "<#{href}>; rel=#{rel}; as=#{as_type}"
375
392
  preload_link += "; type=#{mime_type}" if mime_type
376
393
  preload_link += "; crossorigin=#{crossorigin}" if crossorigin
394
+ preload_link += "; fetchpriority=#{fetchpriority}" if fetchpriority
377
395
  preload_link += "; integrity=#{integrity}" if integrity
396
+ preload_link += "; nonce=#{content_security_policy_nonce}" if add_nonce
378
397
  preload_link += "; nopush" if nopush
379
398
 
380
399
  send_preload_links_header([preload_link])
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "set"
4
-
5
3
  module ActionView
6
4
  module Helpers # :nodoc:
7
5
  # = Action View Atom Feed \Helpers