actionview 7.1.5.2 → 8.1.2.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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +96 -436
  3. data/README.rdoc +1 -1
  4. data/lib/action_view/base.rb +29 -11
  5. data/lib/action_view/buffers.rb +1 -1
  6. data/lib/action_view/cache_expiry.rb +9 -3
  7. data/lib/action_view/dependency_tracker/erb_tracker.rb +37 -28
  8. data/lib/action_view/dependency_tracker/ruby_tracker.rb +43 -0
  9. data/lib/action_view/dependency_tracker/wildcard_resolver.rb +32 -0
  10. data/lib/action_view/dependency_tracker.rb +8 -2
  11. data/lib/action_view/digestor.rb +6 -2
  12. data/lib/action_view/gem_version.rb +3 -3
  13. data/lib/action_view/helpers/asset_tag_helper.rb +39 -8
  14. data/lib/action_view/helpers/atom_feed_helper.rb +1 -3
  15. data/lib/action_view/helpers/cache_helper.rb +10 -2
  16. data/lib/action_view/helpers/capture_helper.rb +2 -2
  17. data/lib/action_view/helpers/controller_helper.rb +6 -2
  18. data/lib/action_view/helpers/csrf_helper.rb +1 -1
  19. data/lib/action_view/helpers/date_helper.rb +28 -4
  20. data/lib/action_view/helpers/form_helper.rb +277 -272
  21. data/lib/action_view/helpers/form_options_helper.rb +39 -35
  22. data/lib/action_view/helpers/form_tag_helper.rb +115 -72
  23. data/lib/action_view/helpers/javascript_helper.rb +5 -1
  24. data/lib/action_view/helpers/number_helper.rb +14 -0
  25. data/lib/action_view/helpers/output_safety_helper.rb +5 -6
  26. data/lib/action_view/helpers/rendering_helper.rb +160 -50
  27. data/lib/action_view/helpers/sanitize_helper.rb +6 -0
  28. data/lib/action_view/helpers/tag_helper.rb +225 -48
  29. data/lib/action_view/helpers/tags/base.rb +11 -9
  30. data/lib/action_view/helpers/tags/check_box.rb +9 -3
  31. data/lib/action_view/helpers/tags/collection_check_boxes.rb +4 -3
  32. data/lib/action_view/helpers/tags/collection_helpers.rb +2 -1
  33. data/lib/action_view/helpers/tags/datetime_field.rb +1 -1
  34. data/lib/action_view/helpers/tags/file_field.rb +7 -2
  35. data/lib/action_view/helpers/tags/hidden_field.rb +1 -1
  36. data/lib/action_view/helpers/tags/label.rb +3 -10
  37. data/lib/action_view/helpers/tags/radio_button.rb +1 -1
  38. data/lib/action_view/helpers/tags/select.rb +6 -1
  39. data/lib/action_view/helpers/tags/select_renderer.rb +6 -4
  40. data/lib/action_view/helpers/tags/text_area.rb +1 -1
  41. data/lib/action_view/helpers/tags/text_field.rb +1 -1
  42. data/lib/action_view/helpers/text_helper.rb +11 -4
  43. data/lib/action_view/helpers/translation_helper.rb +6 -1
  44. data/lib/action_view/helpers/url_helper.rb +42 -90
  45. data/lib/action_view/layouts.rb +9 -11
  46. data/lib/action_view/locale/en.yml +3 -0
  47. data/lib/action_view/log_subscriber.rb +9 -8
  48. data/lib/action_view/railtie.rb +12 -2
  49. data/lib/action_view/record_identifier.rb +22 -1
  50. data/lib/action_view/render_parser/prism_render_parser.rb +139 -0
  51. data/lib/action_view/{ripper_ast_parser.rb → render_parser/ripper_render_parser.rb} +162 -10
  52. data/lib/action_view/render_parser.rb +21 -169
  53. data/lib/action_view/renderer/abstract_renderer.rb +1 -1
  54. data/lib/action_view/renderer/partial_renderer.rb +18 -2
  55. data/lib/action_view/renderer/renderer.rb +32 -38
  56. data/lib/action_view/renderer/streaming_template_renderer.rb +8 -2
  57. data/lib/action_view/renderer/template_renderer.rb +3 -3
  58. data/lib/action_view/rendering.rb +6 -7
  59. data/lib/action_view/structured_event_subscriber.rb +97 -0
  60. data/lib/action_view/template/error.rb +18 -3
  61. data/lib/action_view/template/handlers/erb/erubi.rb +1 -1
  62. data/lib/action_view/template/handlers/erb.rb +77 -44
  63. data/lib/action_view/template/raw_file.rb +4 -0
  64. data/lib/action_view/template/renderable.rb +7 -1
  65. data/lib/action_view/template/resolver.rb +0 -3
  66. data/lib/action_view/template.rb +39 -12
  67. data/lib/action_view/test_case.rb +57 -62
  68. data/lib/action_view.rb +4 -0
  69. metadata +17 -14
  70. data/lib/action_view/dependency_tracker/ripper_tracker.rb +0 -59
@@ -26,6 +26,8 @@ module ActionView
26
26
 
27
27
  # Delegates to ActiveSupport::NumberHelper#number_to_phone.
28
28
  #
29
+ # number_to_phone("1234567890") # => "123-456-7890"
30
+ #
29
31
  # Additionally, supports a +:raise+ option that will cause
30
32
  # InvalidNumberError to be raised if +number+ is not a valid number:
31
33
  #
@@ -42,6 +44,8 @@ module ActionView
42
44
 
43
45
  # Delegates to ActiveSupport::NumberHelper#number_to_currency.
44
46
  #
47
+ # number_to_currency("1234") # => "$1234.00"
48
+ #
45
49
  # Additionally, supports a +:raise+ option that will cause
46
50
  # InvalidNumberError to be raised if +number+ is not a valid number:
47
51
  #
@@ -54,6 +58,8 @@ module ActionView
54
58
 
55
59
  # Delegates to ActiveSupport::NumberHelper#number_to_percentage.
56
60
  #
61
+ # number_to_percentage("99") # => "99.000%"
62
+ #
57
63
  # Additionally, supports a +:raise+ option that will cause
58
64
  # InvalidNumberError to be raised if +number+ is not a valid number:
59
65
  #
@@ -66,6 +72,8 @@ module ActionView
66
72
 
67
73
  # Delegates to ActiveSupport::NumberHelper#number_to_delimited.
68
74
  #
75
+ # number_with_delimiter("1234") # => "1,234"
76
+ #
69
77
  # Additionally, supports a +:raise+ option that will cause
70
78
  # InvalidNumberError to be raised if +number+ is not a valid number:
71
79
  #
@@ -78,6 +86,8 @@ module ActionView
78
86
 
79
87
  # Delegates to ActiveSupport::NumberHelper#number_to_rounded.
80
88
  #
89
+ # number_with_precision("1234") # => "1234.000"
90
+ #
81
91
  # Additionally, supports a +:raise+ option that will cause
82
92
  # InvalidNumberError to be raised if +number+ is not a valid number:
83
93
  #
@@ -90,6 +100,8 @@ module ActionView
90
100
 
91
101
  # Delegates to ActiveSupport::NumberHelper#number_to_human_size.
92
102
  #
103
+ # number_to_human_size("1234") # => "1.21 KB"
104
+ #
93
105
  # Additionally, supports a +:raise+ option that will cause
94
106
  # InvalidNumberError to be raised if +number+ is not a valid number:
95
107
  #
@@ -102,6 +114,8 @@ module ActionView
102
114
 
103
115
  # Delegates to ActiveSupport::NumberHelper#number_to_human.
104
116
  #
117
+ # number_to_human("1234") # => "1.23 Thousand"
118
+ #
105
119
  # Additionally, supports a +:raise+ option that will cause
106
120
  # InvalidNumberError to be raised if +number+ is not a valid number:
107
121
  #
@@ -24,11 +24,11 @@ module ActionView # :nodoc:
24
24
  # the supplied separator, are HTML escaped unless they are HTML
25
25
  # safe, and the returned string is marked as HTML safe.
26
26
  #
27
- # safe_join([raw("<p>foo</p>"), "<p>bar</p>"], "<br />")
28
- # # => "<p>foo</p>&lt;br /&gt;&lt;p&gt;bar&lt;/p&gt;"
27
+ # safe_join([tag.p("foo"), "<p>bar</p>"], "<br>")
28
+ # # => "<p>foo</p>&lt;br&gt;&lt;p&gt;bar&lt;/p&gt;"
29
29
  #
30
- # safe_join([raw("<p>foo</p>"), raw("<p>bar</p>")], raw("<br />"))
31
- # # => "<p>foo</p><br /><p>bar</p>"
30
+ # safe_join([tag.p("foo"), tag.p("bar")], tag.br)
31
+ # # => "<p>foo</p><br><p>bar</p>"
32
32
  #
33
33
  def safe_join(array, sep = $,)
34
34
  sep = ERB::Util.unwrapped_html_escape(sep)
@@ -38,8 +38,7 @@ module ActionView # :nodoc:
38
38
 
39
39
  # Converts the array to a comma-separated sentence where the last element is
40
40
  # joined by the connector word. This is the html_safe-aware version of
41
- # ActiveSupport's {Array#to_sentence}[https://api.rubyonrails.org/classes/Array.html#method-i-to_sentence].
42
- #
41
+ # ActiveSupport's Array#to_sentence.
43
42
  def to_sentence(array, options = {})
44
43
  options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
45
44
 
@@ -1,32 +1,140 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionView
4
6
  module Helpers # :nodoc:
5
- # = Action View \Rendering \Helpers
7
+ # # Action View Rendering Helpers
6
8
  #
7
- # Implements methods that allow rendering from a view context.
8
- # In order to use this module, all you need is to implement
9
- # view_renderer that returns an ActionView::Renderer object.
9
+ # Implements methods that allow rendering from a view context. In order to use
10
+ # this module, all you need is to implement view_renderer that returns an
11
+ # ActionView::Renderer object.
10
12
  module RenderingHelper
11
- # Returns the result of a render that's dictated by the options hash. The primary options are:
13
+ # Renders a template and returns the result.
14
+ #
15
+ # Pass the template to render as the first argument. This is shorthand
16
+ # syntax for partial rendering, so the template filename should be
17
+ # prefixed with an underscore. The partial renderer looks for the partial
18
+ # template in the directory of the calling template first.
19
+ #
20
+ # <% # app/views/posts/new.html.erb %>
21
+ # <%= render "form" %>
22
+ # # => renders app/views/posts/_form.html.erb
23
+ #
24
+ # Use the complete view path to render a partial from another directory.
25
+ #
26
+ # <% # app/views/posts/show.html.erb %>
27
+ # <%= render "comments/form" %>
28
+ # # => renders app/views/comments/_form.html.erb
29
+ #
30
+ # Without the rendering mode, the second argument can be a Hash of local
31
+ # variable assignments for the template.
32
+ #
33
+ # <% # app/views/posts/new.html.erb %>
34
+ # <%= render "form", post: Post.new %>
35
+ # # => renders app/views/posts/_form.html.erb
36
+ #
37
+ # If the first argument responds to `render_in`, the template will be rendered
38
+ # by calling `render_in` with the current view context.
39
+ #
40
+ # class Greeting
41
+ # def render_in(view_context)
42
+ # view_context.render html: "<h1>Hello, World</h1>"
43
+ # end
44
+ #
45
+ # def format
46
+ # :html
47
+ # end
48
+ # end
49
+ #
50
+ # <%= render Greeting.new %>
51
+ # # => "<h1>Hello, World</h1>"
52
+ #
53
+ # #### Rendering Mode
54
+ #
55
+ # Pass the rendering mode as first argument to override it.
56
+ #
57
+ # `:partial`
58
+ # : See ActionView::PartialRenderer for details.
59
+ #
60
+ # <%= render partial: "form", locals: { post: Post.new } %>
61
+ # # => renders app/views/posts/_form.html.erb
62
+ #
63
+ # `:file`
64
+ # : Renders the contents of a file. This option should **not** be used with
65
+ # unsanitized user input.
66
+ #
67
+ # <%= render file: "/path/to/some/file" %>
68
+ # # => renders /path/to/some/file
69
+ #
70
+ # `:inline`
71
+ # : Renders an ERB template string.
72
+ #
73
+ # <% name = "World" %>
74
+ # <%= render inline: "<h1>Hello, <%= name %>!</h1>" %>
75
+ # # => renders "<h1>Hello, World!</h1>"
76
+ #
77
+ # `:body`
78
+ # : Renders the provided text, and sets the format as `:text`.
79
+ #
80
+ # <%= render body: "Hello, World!" %>
81
+ # # => renders "Hello, World!"
82
+ #
83
+ # `:plain`
84
+ # : Renders the provided text, and sets the format as `:text`.
85
+ #
86
+ # <%= render plain: "Hello, World!" %>
87
+ # # => renders "Hello, World!"
88
+ #
89
+ # `:html`
90
+ # : Renders the provided HTML string, and sets the format as
91
+ # `:html`. If the string is not `html_safe?`, performs HTML escaping on
92
+ # the string before rendering.
93
+ #
94
+ # <%= render html: "<h1>Hello, World!</h1>".html_safe %>
95
+ # # => renders "<h1>Hello, World!</h1>"
96
+ #
97
+ # <%= render html: "<h1>Hello, World!</h1>" %>
98
+ # # => renders "&lt;h1&gt;Hello, World!&lt;/h1&gt;"
99
+ #
100
+ # `:renderable`
101
+ # : Renders the provided object by calling `render_in` with the current view
102
+ # context. The format is determined by calling `format` on the
103
+ # renderable if it responds to `format`, falling back to `:html` by
104
+ # default.
105
+ #
106
+ # <%= render renderable: Greeting.new %>
107
+ # # => renders "<h1>Hello, World</h1>"
108
+ #
109
+ #
110
+ # #### Options
111
+ #
112
+ # `:locals`
113
+ # : Hash of local variable assignments for the template.
114
+ #
115
+ # <%= render inline: "<h1>Hello, <%= name %>!</h1>", locals: { name: "World" } %>
116
+ # # => renders "<h1>Hello, World!</h1>"
117
+ #
118
+ # `:formats`
119
+ # : Override the current format to render a template for a different format.
120
+ #
121
+ # <% # app/views/posts/show.html.erb %>
122
+ # <%= render template: "posts/content", formats: [:text] %>
123
+ # # => renders app/views/posts/content.text.erb
12
124
  #
13
- # * <tt>:partial</tt> - See ActionView::PartialRenderer.
14
- # * <tt>:file</tt> - Renders an explicit template file (this used to be the old default), add +:locals+ to pass in those.
15
- # * <tt>:inline</tt> - Renders an inline template similar to how it's done in the controller.
16
- # * <tt>:plain</tt> - Renders the text passed in out. Setting the content
17
- # type as <tt>text/plain</tt>.
18
- # * <tt>:html</tt> - Renders the HTML safe string passed in out, otherwise
19
- # performs HTML escape on the string first. Setting the content type as
20
- # <tt>text/html</tt>.
21
- # * <tt>:body</tt> - Renders the text passed in, and inherits the content
22
- # type of <tt>text/plain</tt> from ActionDispatch::Response object.
125
+ # `:variants`
126
+ # : Render a template for a different variant.
23
127
  #
24
- # If no <tt>options</tt> hash is passed or if <tt>:update</tt> is specified, then:
128
+ # <% # app/views/posts/show.html.erb %>
129
+ # <%= render template: "posts/content", variants: [:tablet] %>
130
+ # # => renders app/views/posts/content.html+tablet.erb
25
131
  #
26
- # If an object responding to +render_in+ is passed, +render_in+ is called on the object,
27
- # passing in the current view context.
132
+ # `:handlers`
133
+ # : Render a template for a different handler.
28
134
  #
29
- # Otherwise, a partial is rendered using the second parameter as the locals hash.
135
+ # <% # app/views/posts/show.html.erb %>
136
+ # <%= render template: "posts/content", handlers: [:builder] %>
137
+ # # => renders app/views/posts/content.html.builder
30
138
  def render(options = {}, locals = {}, &block)
31
139
  case options
32
140
  when Hash
@@ -47,52 +155,54 @@ module ActionView
47
155
  end
48
156
 
49
157
  # Overrides _layout_for in the context object so it supports the case a block is
50
- # passed to a partial. Returns the contents that are yielded to a layout, given a
51
- # name or a block.
158
+ # passed to a partial. Returns the contents that are yielded to a layout, given
159
+ # a name or a block.
52
160
  #
53
- # You can think of a layout as a method that is called with a block. If the user calls
54
- # <tt>yield :some_name</tt>, the block, by default, returns <tt>content_for(:some_name)</tt>.
55
- # If the user calls simply +yield+, the default block returns <tt>content_for(:layout)</tt>.
161
+ # You can think of a layout as a method that is called with a block. If the user
162
+ # calls `yield :some_name`, the block, by default, returns
163
+ # `content_for(:some_name)`. If the user calls simply `yield`, the default block
164
+ # returns `content_for(:layout)`.
56
165
  #
57
166
  # The user can override this default by passing a block to the layout:
58
167
  #
59
- # # The template
60
- # <%= render layout: "my_layout" do %>
61
- # Content
62
- # <% end %>
168
+ # # The template
169
+ # <%= render layout: "my_layout" do %>
170
+ # Content
171
+ # <% end %>
63
172
  #
64
- # # The layout
65
- # <html>
66
- # <%= yield %>
67
- # </html>
173
+ # # The layout
174
+ # <html>
175
+ # <%= yield %>
176
+ # </html>
68
177
  #
69
- # In this case, instead of the default block, which would return <tt>content_for(:layout)</tt>,
70
- # this method returns the block that was passed in to <tt>render :layout</tt>, and the response
178
+ # In this case, instead of the default block, which would return `content_for(:layout)`,
179
+ # this method returns the block that was passed in to `render :layout`, and the response
71
180
  # would be
72
181
  #
73
- # <html>
74
- # Content
75
- # </html>
182
+ # <html>
183
+ # Content
184
+ # </html>
76
185
  #
77
- # Finally, the block can take block arguments, which can be passed in by +yield+:
186
+ # Finally, the block can take block arguments, which can be passed in by
187
+ # `yield`:
78
188
  #
79
- # # The template
80
- # <%= render layout: "my_layout" do |customer| %>
81
- # Hello <%= customer.name %>
82
- # <% end %>
189
+ # # The template
190
+ # <%= render layout: "my_layout" do |customer| %>
191
+ # Hello <%= customer.name %>
192
+ # <% end %>
83
193
  #
84
- # # The layout
85
- # <html>
86
- # <%= yield Struct.new(:name).new("David") %>
87
- # </html>
194
+ # # The layout
195
+ # <html>
196
+ # <%= yield Struct.new(:name).new("David") %>
197
+ # </html>
88
198
  #
89
- # In this case, the layout would receive the block passed into <tt>render :layout</tt>,
199
+ # In this case, the layout would receive the block passed into `render :layout`,
90
200
  # and the struct specified would be passed into the block as an argument. The result
91
201
  # would be
92
202
  #
93
- # <html>
94
- # Hello David
95
- # </html>
203
+ # <html>
204
+ # Hello David
205
+ # </html>
96
206
  #
97
207
  def _layout_for(*args, &block)
98
208
  name = args.first
@@ -24,6 +24,12 @@ module ActionView
24
24
  #
25
25
  # Custom sanitization rules can also be provided.
26
26
  #
27
+ # <b>Warning</b>: Adding disallowed tags or attributes to the allowlists may introduce
28
+ # vulnerabilities into your application. Please rely on the default allowlists whenever
29
+ # possible, because they are curated to maintain security and safety. If you think that the
30
+ # default allowlists should be expanded, please {open an issue on the rails-html-sanitizer
31
+ # project}[https://github.com/rails/rails-html-sanitizer/issues].
32
+ #
27
33
  # Please note that sanitizing user-provided text does not guarantee that the
28
34
  # resulting markup is valid or even well-formed.
29
35
  #