actionview 7.1.0 → 7.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32185e4d0d7cd6d977741871632481ac24d5e8dc510ffdd91738c704c6a7713f
4
- data.tar.gz: 18f1a181d6ca4aa6f0572e269b79046384ce61a76eaa3a7d8c94535de1119d4c
3
+ metadata.gz: 2ec34555888d78ec7dd238a5845d5a0a6861aabf4b43b532b9001de74d7f69f8
4
+ data.tar.gz: fa36f1e81bea968392435051307a0ad371e856f8fa4760b6e341df5412a017e5
5
5
  SHA512:
6
- metadata.gz: db7eeb976f3e336aec8472acd0a4a4cb9fbfb7aded98236c671d98d0c081fd1331be49a67127c619691931c7f8317b0fa7af0205bd26627f11d61dfe313f2bd4
7
- data.tar.gz: abd1bff9bf3b89b81fb8008641cd77299892b856b19a2788bd25d913af2c2d78963bdda2157b14aa7c7ac03a3300ef41e6acdf2ac836580406df2710d08ee6e1
6
+ metadata.gz: 229637c660fba19dcba6f8e15e83cf748b1e8ee0c123bc32d2b0417265df296254dfd3f9ef07d64b930f96c1e1b94a3ad9f9304a9c9e4ce734357208924019f7
7
+ data.tar.gz: 5ef080a91aa2611698efca00142c79aa3f005ab680cbe804c41636df0318f05ce432429a3420d06515be43f2d249e7d38d8b9e7496d64b58a9ba218451310808
data/CHANGELOG.md CHANGED
@@ -1,3 +1,39 @@
1
+ ## Rails 7.1.2 (November 10, 2023) ##
2
+
3
+ * Fix the `number_to_human_size` view helper to correctly work with negative numbers.
4
+
5
+ *Earlopain*
6
+
7
+ * Automatically discard the implicit locals injected by collection rendering for template that can't accept them
8
+
9
+ When rendering a collection, two implicit variables are injected, which breaks templates with strict locals.
10
+
11
+ Now they are only passed if the template will actually accept them.
12
+
13
+ *Yasha Krasnou*, *Jean Boussier*
14
+
15
+ * Fix `@rails/ujs` calling `start()` an extra time when using bundlers
16
+
17
+ *Hartley McGuire*, *Ryunosuke Sato*
18
+
19
+ * Fix the `capture` view helper compatibility with HAML and Slim
20
+
21
+ When a blank string was captured in HAML or Slim (and possibly other template engines)
22
+ it would instead return the entire buffer.
23
+
24
+ *Jean Boussier*
25
+
26
+
27
+ ## Rails 7.1.1 (October 11, 2023) ##
28
+
29
+ * Updated `@rails/ujs` files to ignore certain data-* attributes when element is contenteditable.
30
+
31
+ This fix was already landed in >= 7.0.4.3, < 7.1.0.
32
+ [[CVE-2023-23913](https://github.com/advisories/GHSA-xp5h-f8jf-rc8q)]
33
+
34
+ *Ryunosuke Sato*
35
+
36
+
1
37
  ## Rails 7.1.0 (October 05, 2023) ##
2
38
 
3
39
  * No changes.
@@ -58,6 +58,18 @@ const setData = function(element, key, value) {
58
58
 
59
59
  const $ = selector => Array.prototype.slice.call(document.querySelectorAll(selector));
60
60
 
61
+ const isContentEditable = function(element) {
62
+ var isEditable = false;
63
+ do {
64
+ if (element.isContentEditable) {
65
+ isEditable = true;
66
+ break;
67
+ }
68
+ element = element.parentElement;
69
+ } while (element);
70
+ return isEditable;
71
+ };
72
+
61
73
  const csrfToken = () => {
62
74
  const meta = document.querySelector("meta[name=csrf-token]");
63
75
  return meta && meta.content;
@@ -336,6 +348,9 @@ const enableElement = e => {
336
348
  } else {
337
349
  element = e;
338
350
  }
351
+ if (isContentEditable(element)) {
352
+ return;
353
+ }
339
354
  if (matches(element, linkDisableSelector)) {
340
355
  return enableLinkElement(element);
341
356
  } else if (matches(element, buttonDisableSelector) || matches(element, formEnableSelector)) {
@@ -347,6 +362,9 @@ const enableElement = e => {
347
362
 
348
363
  const disableElement = e => {
349
364
  const element = e instanceof Event ? e.target : e;
365
+ if (isContentEditable(element)) {
366
+ return;
367
+ }
350
368
  if (matches(element, linkDisableSelector)) {
351
369
  return disableLinkElement(element);
352
370
  } else if (matches(element, buttonDisableSelector) || matches(element, formDisableSelector)) {
@@ -426,6 +444,9 @@ const handleMethodWithRails = rails => function(e) {
426
444
  if (!method) {
427
445
  return;
428
446
  }
447
+ if (isContentEditable(this)) {
448
+ return;
449
+ }
429
450
  const href = rails.href(link);
430
451
  const csrfToken$1 = csrfToken();
431
452
  const csrfParam$1 = csrfParam();
@@ -460,6 +481,10 @@ const handleRemoteWithRails = rails => function(e) {
460
481
  fire(element, "ajax:stopped");
461
482
  return false;
462
483
  }
484
+ if (isContentEditable(element)) {
485
+ fire(element, "ajax:stopped");
486
+ return false;
487
+ }
463
488
  const withCredentials = element.getAttribute("data-with-credentials");
464
489
  const dataType = element.getAttribute("data-type") || "script";
465
490
  if (matches(element, formSubmitSelector)) {
@@ -658,11 +683,4 @@ if (typeof jQuery !== "undefined" && jQuery && jQuery.ajax) {
658
683
  }));
659
684
  }
660
685
 
661
- if (typeof exports !== "object" && typeof module === "undefined") {
662
- window.Rails = Rails;
663
- if (fire(document, "rails:attachBindings")) {
664
- start();
665
- }
666
- }
667
-
668
- export default Rails;
686
+ export { Rails as default };
@@ -44,6 +44,17 @@ Released under the MIT license
44
44
  return element[EXPANDO][key] = value;
45
45
  };
46
46
  const $ = selector => Array.prototype.slice.call(document.querySelectorAll(selector));
47
+ const isContentEditable = function(element) {
48
+ var isEditable = false;
49
+ do {
50
+ if (element.isContentEditable) {
51
+ isEditable = true;
52
+ break;
53
+ }
54
+ element = element.parentElement;
55
+ } while (element);
56
+ return isEditable;
57
+ };
47
58
  const csrfToken = () => {
48
59
  const meta = document.querySelector("meta[name=csrf-token]");
49
60
  return meta && meta.content;
@@ -298,6 +309,9 @@ Released under the MIT license
298
309
  } else {
299
310
  element = e;
300
311
  }
312
+ if (isContentEditable(element)) {
313
+ return;
314
+ }
301
315
  if (matches(element, linkDisableSelector)) {
302
316
  return enableLinkElement(element);
303
317
  } else if (matches(element, buttonDisableSelector) || matches(element, formEnableSelector)) {
@@ -308,6 +322,9 @@ Released under the MIT license
308
322
  };
309
323
  const disableElement = e => {
310
324
  const element = e instanceof Event ? e.target : e;
325
+ if (isContentEditable(element)) {
326
+ return;
327
+ }
311
328
  if (matches(element, linkDisableSelector)) {
312
329
  return disableLinkElement(element);
313
330
  } else if (matches(element, buttonDisableSelector) || matches(element, formDisableSelector)) {
@@ -379,6 +396,9 @@ Released under the MIT license
379
396
  if (!method) {
380
397
  return;
381
398
  }
399
+ if (isContentEditable(this)) {
400
+ return;
401
+ }
382
402
  const href = rails.href(link);
383
403
  const csrfToken$1 = csrfToken();
384
404
  const csrfParam$1 = csrfParam();
@@ -411,6 +431,10 @@ Released under the MIT license
411
431
  fire(element, "ajax:stopped");
412
432
  return false;
413
433
  }
434
+ if (isContentEditable(element)) {
435
+ fire(element, "ajax:stopped");
436
+ return false;
437
+ }
414
438
  const withCredentials = element.getAttribute("data-with-credentials");
415
439
  const dataType = element.getAttribute("data-type") || "script";
416
440
  if (matches(element, formSubmitSelector)) {
@@ -9,7 +9,7 @@ module ActionView
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 1
12
- TINY = 0
12
+ TINY = 2
13
13
  PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -378,8 +378,8 @@ module ActionView
378
378
  # You can add HTML attributes using the +options+. The +options+ supports
379
379
  # additional keys for convenience and conformance:
380
380
  #
381
- # * <tt>:size</tt> - Supplied as "{Width}x{Height}" or "{Number}", so "30x45" becomes
382
- # width="30" and height="45", and "50" becomes width="50" and height="50".
381
+ # * <tt>:size</tt> - Supplied as <tt>"#{width}x#{height}"</tt> or <tt>"#{number}"</tt>, so <tt>"30x45"</tt> becomes
382
+ # <tt>width="30" height="45"</tt>, and <tt>"50"</tt> becomes <tt>width="50" height="50"</tt>.
383
383
  # <tt>:size</tt> will be ignored if the value is not in the correct format.
384
384
  # * <tt>:srcset</tt> - If supplied as a hash or array of <tt>[source, descriptor]</tt>
385
385
  # pairs, each image path will be expanded before the list is formatted as a string.
@@ -511,8 +511,8 @@ module ActionView
511
511
  #
512
512
  # * <tt>:poster</tt> - Set an image (like a screenshot) to be shown
513
513
  # before the video loads. The path is calculated like the +src+ of +image_tag+.
514
- # * <tt>:size</tt> - Supplied as "{Width}x{Height}" or "{Number}", so "30x45" becomes
515
- # width="30" and height="45", and "50" becomes width="50" and height="50".
514
+ # * <tt>:size</tt> - Supplied as <tt>"#{width}x#{height}"</tt> or <tt>"#{number}"</tt>, so <tt>"30x45"</tt> becomes
515
+ # <tt>width="30" height="45"</tt>, and <tt>"50"</tt> becomes <tt>width="50" height="50"</tt>.
516
516
  # <tt>:size</tt> will be ignored if the value is not in the correct format.
517
517
  # * <tt>:poster_skip_pipeline</tt> will bypass the asset pipeline when using
518
518
  # the <tt>:poster</tt> option instead using an asset in the public folder.
@@ -49,7 +49,13 @@ module ActionView
49
49
  @output_buffer ||= ActionView::OutputBuffer.new
50
50
  buffer = @output_buffer.capture { value = yield(*args) }
51
51
 
52
- case string = buffer.presence || value
52
+ string = if @output_buffer.equal?(value)
53
+ buffer
54
+ else
55
+ buffer.presence || value
56
+ end
57
+
58
+ case string
53
59
  when OutputBuffer
54
60
  string.to_s
55
61
  when ActiveSupport::SafeBuffer
@@ -1783,7 +1783,7 @@ module ActionView
1783
1783
  # <% end %>
1784
1784
  #
1785
1785
  # <%= form_for @post do |f| %>
1786
- # <%= f.field_tag :tag, name: f.field_name(:tag, multiple: true) %>
1786
+ # <%= f.text_field :tag, name: f.field_name(:tag, multiple: true) %>
1787
1787
  # <%# => <input type="text" name="post[tag][]">
1788
1788
  # <% end %>
1789
1789
  #
@@ -2263,7 +2263,7 @@ module ActionView
2263
2263
  # <% end %>
2264
2264
  #
2265
2265
  # When a collection is used you might want to know the index of each
2266
- # object into the array. For this purpose, the <tt>index</tt> method
2266
+ # object in the array. For this purpose, the <tt>index</tt> method
2267
2267
  # is available in the FormBuilder object.
2268
2268
  #
2269
2269
  # <%= form_for @person do |person_form| %>
@@ -194,7 +194,7 @@ module ActionView
194
194
 
195
195
  _template = (cache[path] ||= (template || find_template(path, @locals.keys + [as, counter, iteration])))
196
196
 
197
- content = _template.render(view, locals)
197
+ content = _template.render(view, locals, implicit_locals: [counter, iteration])
198
198
  content = layout.render(view, locals) { content } if layout
199
199
  partial_iteration.iterate!
200
200
  build_rendered_template(content, _template)
@@ -201,6 +201,7 @@ module ActionView
201
201
  @variant = variant
202
202
  @compile_mutex = Mutex.new
203
203
  @strict_locals = NONE
204
+ @strict_local_keys = nil
204
205
  @type = nil
205
206
  end
206
207
 
@@ -244,9 +245,15 @@ module ActionView
244
245
  # This method is instrumented as "!render_template.action_view". Notice that
245
246
  # we use a bang in this instrumentation because you don't want to
246
247
  # consume this in production. This is only slow if it's being listened to.
247
- def render(view, locals, buffer = nil, add_to_stack: true, &block)
248
+ def render(view, locals, buffer = nil, implicit_locals: [], add_to_stack: true, &block)
248
249
  instrument_render_template do
249
250
  compile!(view)
251
+
252
+ if strict_locals? && @strict_local_keys && !implicit_locals.empty?
253
+ locals_to_ignore = implicit_locals - @strict_local_keys
254
+ locals.except!(*locals_to_ignore)
255
+ end
256
+
250
257
  if buffer
251
258
  view._run(method_name, self, locals, buffer, add_to_stack: add_to_stack, has_strict_locals: strict_locals?, &block)
252
259
  nil
@@ -283,7 +290,7 @@ module ActionView
283
290
  # the same as <tt>Encoding.default_external</tt>.
284
291
  #
285
292
  # The user can also specify the encoding via a comment on the first
286
- # line of the template (# encoding: NAME-OF-ENCODING). This will work
293
+ # line of the template (<tt># encoding: NAME-OF-ENCODING</tt>). This will work
287
294
  # with any template engine, as we process out the encoding comment
288
295
  # before passing the source on to the template engine, leaving a
289
296
  # blank line in its stead.
@@ -474,23 +481,30 @@ module ActionView
474
481
 
475
482
  return unless strict_locals?
476
483
 
484
+ parameters = mod.instance_method(method_name).parameters - [[:req, :output_buffer]]
477
485
  # Check compiled method parameters to ensure that only kwargs
478
486
  # were provided as strict locals, preventing `locals: (foo, *foo)` etc
479
487
  # and allowing `locals: (foo:)`.
480
488
 
481
- non_kwarg_parameters =
482
- (mod.instance_method(method_name).parameters - [[:req, :output_buffer]]).
483
- select { |parameter| ![:keyreq, :key, :keyrest, :nokey].include?(parameter[0]) }
489
+ non_kwarg_parameters = parameters.select do |parameter|
490
+ ![:keyreq, :key, :keyrest, :nokey].include?(parameter[0])
491
+ end
484
492
 
485
- return unless non_kwarg_parameters.any?
493
+ unless non_kwarg_parameters.empty?
494
+ mod.undef_method(method_name)
486
495
 
487
- mod.undef_method(method_name)
496
+ raise ArgumentError.new(
497
+ "#{non_kwarg_parameters.map { |_, name| "`#{name}`" }.to_sentence} set as non-keyword " \
498
+ "#{'argument'.pluralize(non_kwarg_parameters.length)} for #{short_identifier}. " \
499
+ "Locals can only be set as keyword arguments."
500
+ )
501
+ end
488
502
 
489
- raise ArgumentError.new(
490
- "#{non_kwarg_parameters.map { |_, name| "`#{name}`" }.to_sentence} set as non-keyword " \
491
- "#{'argument'.pluralize(non_kwarg_parameters.length)} for #{short_identifier}. " \
492
- "Locals can only be set as keyword arguments."
493
- )
503
+ unless parameters.any? { |type, _| type == :keyrest }
504
+ parameters.map!(&:first)
505
+ parameters.sort!
506
+ @strict_local_keys = parameters.freeze
507
+ end
494
508
  end
495
509
 
496
510
  def offset
@@ -82,25 +82,27 @@ module ActionView
82
82
  # method, where +[FORMAT]+ corresponds to the value of the
83
83
  # +format+ argument.
84
84
  #
85
- # === Arguments
85
+ # By default, ActionView::TestCase defines parsers for:
86
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.
87
+ # * +:html+ - returns an instance of +Nokogiri::XML::Node+
88
+ # * +:json+ - returns an instance of ActiveSupport::HashWithIndifferentAccess
92
89
  #
93
- # By default, ActionView::TestCase defines a parser for:
90
+ # These pre-registered parsers also define corresponding helpers:
94
91
  #
95
- # * :html - returns an instance of Nokogiri::XML::Node
96
- # * :json - returns an instance of ActiveSupport::HashWithIndifferentAccess
92
+ # * +:html+ - defines +rendered.html+
93
+ # * +:json+ - defines +rendered.json+
97
94
  #
98
- # Each pre-registered parser also defines a corresponding helper:
95
+ # ==== Parameters
99
96
  #
100
- # * :html - defines `rendered.html`
101
- # * :json - defines `rendered.json`
97
+ # [+format+]
98
+ # The name (as a +Symbol+) of the format used to render the content.
102
99
  #
103
- # === Examples
100
+ # [+callable+]
101
+ # The parser. A callable object that accepts the rendered string as
102
+ # its sole argument. Alternatively, the parser can be specified as a
103
+ # block.
104
+ #
105
+ # ==== Examples
104
106
  #
105
107
  # test "renders HTML" do
106
108
  # article = Article.create!(title: "Hello, world")
@@ -118,7 +120,7 @@ module ActionView
118
120
  # assert_pattern { rendered.json => { title: "Hello, world" } }
119
121
  # end
120
122
  #
121
- # To parse the rendered content into RSS, register a call to <tt>RSS::Parser.parse</tt>:
123
+ # To parse the rendered content into RSS, register a call to +RSS::Parser.parse+:
122
124
  #
123
125
  # register_parser :rss, -> rendered { RSS::Parser.parse(rendered) }
124
126
  #
@@ -130,9 +132,8 @@ module ActionView
130
132
  # assert_equal "Hello, world", rendered.rss.items.last.title
131
133
  # end
132
134
  #
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>:
135
+ # To parse the rendered content into a +Capybara::Simple::Node+,
136
+ # re-register an +:html+ parser with a call to +Capybara.string+:
136
137
  #
137
138
  # register_parser :html, -> rendered { Capybara.string(rendered) }
138
139
  #
@@ -143,6 +144,7 @@ module ActionView
143
144
  #
144
145
  # rendered.html.assert_css "h1", text: "Hello, world"
145
146
  # end
147
+ #
146
148
  def register_parser(format, callable = nil, &block)
147
149
  parser = callable || block || :itself.to_proc
148
150
  content_class.redefine_method(format) do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionview
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.0
4
+ version: 7.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-05 00:00:00.000000000 Z
11
+ date: 2023-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 7.1.0
19
+ version: 7.1.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 7.1.0
26
+ version: 7.1.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: builder
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -86,28 +86,28 @@ dependencies:
86
86
  requirements:
87
87
  - - '='
88
88
  - !ruby/object:Gem::Version
89
- version: 7.1.0
89
+ version: 7.1.2
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - '='
95
95
  - !ruby/object:Gem::Version
96
- version: 7.1.0
96
+ version: 7.1.2
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: activemodel
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - '='
102
102
  - !ruby/object:Gem::Version
103
- version: 7.1.0
103
+ version: 7.1.2
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - '='
109
109
  - !ruby/object:Gem::Version
110
- version: 7.1.0
110
+ version: 7.1.2
111
111
  description: Simple, battle-tested conventions and helpers for building web pages.
112
112
  email: david@loudthinking.com
113
113
  executables: []
@@ -246,10 +246,10 @@ licenses:
246
246
  - MIT
247
247
  metadata:
248
248
  bug_tracker_uri: https://github.com/rails/rails/issues
249
- changelog_uri: https://github.com/rails/rails/blob/v7.1.0/actionview/CHANGELOG.md
250
- documentation_uri: https://api.rubyonrails.org/v7.1.0/
249
+ changelog_uri: https://github.com/rails/rails/blob/v7.1.2/actionview/CHANGELOG.md
250
+ documentation_uri: https://api.rubyonrails.org/v7.1.2/
251
251
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
252
- source_code_uri: https://github.com/rails/rails/tree/v7.1.0/actionview
252
+ source_code_uri: https://github.com/rails/rails/tree/v7.1.2/actionview
253
253
  rubygems_mfa_required: 'true'
254
254
  post_install_message:
255
255
  rdoc_options: []