actionview 6.1.6.1 → 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.

Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +89 -347
  3. data/MIT-LICENSE +2 -1
  4. data/lib/action_view/base.rb +3 -3
  5. data/lib/action_view/buffers.rb +2 -2
  6. data/lib/action_view/cache_expiry.rb +46 -32
  7. data/lib/action_view/dependency_tracker/erb_tracker.rb +154 -0
  8. data/lib/action_view/dependency_tracker/ripper_tracker.rb +59 -0
  9. data/lib/action_view/dependency_tracker.rb +6 -147
  10. data/lib/action_view/digestor.rb +7 -4
  11. data/lib/action_view/flows.rb +4 -4
  12. data/lib/action_view/gem_version.rb +4 -4
  13. data/lib/action_view/helpers/active_model_helper.rb +1 -1
  14. data/lib/action_view/helpers/asset_tag_helper.rb +84 -29
  15. data/lib/action_view/helpers/asset_url_helper.rb +7 -7
  16. data/lib/action_view/helpers/atom_feed_helper.rb +3 -4
  17. data/lib/action_view/helpers/cache_helper.rb +51 -3
  18. data/lib/action_view/helpers/capture_helper.rb +2 -2
  19. data/lib/action_view/helpers/controller_helper.rb +2 -2
  20. data/lib/action_view/helpers/csp_helper.rb +1 -1
  21. data/lib/action_view/helpers/csrf_helper.rb +1 -1
  22. data/lib/action_view/helpers/date_helper.rb +6 -7
  23. data/lib/action_view/helpers/debug_helper.rb +3 -1
  24. data/lib/action_view/helpers/form_helper.rb +72 -12
  25. data/lib/action_view/helpers/form_options_helper.rb +65 -33
  26. data/lib/action_view/helpers/form_tag_helper.rb +75 -32
  27. data/lib/action_view/helpers/javascript_helper.rb +3 -5
  28. data/lib/action_view/helpers/number_helper.rb +3 -4
  29. data/lib/action_view/helpers/output_safety_helper.rb +2 -2
  30. data/lib/action_view/helpers/rendering_helper.rb +1 -1
  31. data/lib/action_view/helpers/sanitize_helper.rb +2 -2
  32. data/lib/action_view/helpers/tag_helper.rb +25 -44
  33. data/lib/action_view/helpers/tags/base.rb +3 -15
  34. data/lib/action_view/helpers/tags/check_box.rb +2 -2
  35. data/lib/action_view/helpers/tags/collection_select.rb +1 -1
  36. data/lib/action_view/helpers/tags/hidden_field.rb +0 -4
  37. data/lib/action_view/helpers/tags/time_field.rb +10 -1
  38. data/lib/action_view/helpers/tags/weekday_select.rb +27 -0
  39. data/lib/action_view/helpers/tags.rb +3 -2
  40. data/lib/action_view/helpers/text_helper.rb +24 -13
  41. data/lib/action_view/helpers/translation_helper.rb +1 -2
  42. data/lib/action_view/helpers/url_helper.rb +102 -77
  43. data/lib/action_view/helpers.rb +25 -25
  44. data/lib/action_view/lookup_context.rb +33 -52
  45. data/lib/action_view/model_naming.rb +1 -1
  46. data/lib/action_view/path_set.rb +16 -22
  47. data/lib/action_view/railtie.rb +14 -1
  48. data/lib/action_view/render_parser.rb +188 -0
  49. data/lib/action_view/renderer/abstract_renderer.rb +2 -2
  50. data/lib/action_view/renderer/partial_renderer.rb +0 -34
  51. data/lib/action_view/renderer/renderer.rb +4 -4
  52. data/lib/action_view/renderer/streaming_template_renderer.rb +3 -3
  53. data/lib/action_view/renderer/template_renderer.rb +6 -2
  54. data/lib/action_view/rendering.rb +2 -2
  55. data/lib/action_view/ripper_ast_parser.rb +198 -0
  56. data/lib/action_view/routing_url_for.rb +1 -1
  57. data/lib/action_view/template/error.rb +108 -13
  58. data/lib/action_view/template/handlers/erb.rb +6 -0
  59. data/lib/action_view/template/handlers.rb +3 -3
  60. data/lib/action_view/template/html.rb +3 -3
  61. data/lib/action_view/template/inline.rb +3 -3
  62. data/lib/action_view/template/raw_file.rb +3 -3
  63. data/lib/action_view/template/resolver.rb +84 -311
  64. data/lib/action_view/template/text.rb +3 -3
  65. data/lib/action_view/template/types.rb +14 -12
  66. data/lib/action_view/template.rb +10 -1
  67. data/lib/action_view/template_details.rb +66 -0
  68. data/lib/action_view/template_path.rb +64 -0
  69. data/lib/action_view/test_case.rb +6 -2
  70. data/lib/action_view/testing/resolvers.rb +11 -12
  71. data/lib/action_view/unbound_template.rb +33 -7
  72. data/lib/action_view.rb +3 -4
  73. metadata +25 -19
@@ -4,13 +4,13 @@ require "active_support/core_ext/enumerable"
4
4
 
5
5
  module ActionView
6
6
  # = Action View Errors
7
- class ActionViewError < StandardError #:nodoc:
7
+ class ActionViewError < StandardError # :nodoc:
8
8
  end
9
9
 
10
- class EncodingError < StandardError #:nodoc:
10
+ class EncodingError < StandardError # :nodoc:
11
11
  end
12
12
 
13
- class WrongEncodingError < EncodingError #:nodoc:
13
+ class WrongEncodingError < EncodingError # :nodoc:
14
14
  def initialize(string, encoding)
15
15
  @string, @encoding = string, encoding
16
16
  end
@@ -26,12 +26,18 @@ module ActionView
26
26
  end
27
27
  end
28
28
 
29
- class MissingTemplate < ActionViewError #:nodoc:
30
- attr_reader :path
29
+ class MissingTemplate < ActionViewError # :nodoc:
30
+ attr_reader :path, :paths, :prefixes, :partial
31
31
 
32
32
  def initialize(paths, path, prefixes, partial, details, *)
33
+ if partial && path.present?
34
+ path = path.sub(%r{([^/]+)$}, "_\\1")
35
+ end
36
+
33
37
  @path = path
34
- prefixes = Array(prefixes)
38
+ @paths = paths
39
+ @prefixes = Array(prefixes)
40
+ @partial = partial
35
41
  template_type = if partial
36
42
  "partial"
37
43
  elsif /layouts/i.match?(path)
@@ -40,22 +46,111 @@ module ActionView
40
46
  "template"
41
47
  end
42
48
 
43
- if partial && path.present?
44
- path = path.sub(%r{([^/]+)$}, "_\\1")
45
- end
46
- searched_paths = prefixes.map { |prefix| [prefix, path].join("/") }
49
+ searched_paths = @prefixes.map { |prefix| [prefix, path].join("/") }
47
50
 
48
- out = "Missing #{template_type} #{searched_paths.join(", ")} with #{details.inspect}. Searched in:\n"
51
+ out = "Missing #{template_type} #{searched_paths.join(", ")} with #{details.inspect}.\n\nSearched in:\n"
49
52
  out += paths.compact.map { |p| " * #{p.to_s.inspect}\n" }.join
50
53
  super out
51
54
  end
55
+
56
+ if defined?(DidYouMean::Correctable) && defined?(DidYouMean::Jaro)
57
+ include DidYouMean::Correctable
58
+
59
+ class Results # :nodoc:
60
+ Result = Struct.new(:path, :score)
61
+
62
+ def initialize(size)
63
+ @size = size
64
+ @results = []
65
+ end
66
+
67
+ def to_a
68
+ @results.map(&:path)
69
+ end
70
+
71
+ def should_record?(score)
72
+ if @results.size < @size
73
+ true
74
+ else
75
+ score < @results.last.score
76
+ end
77
+ end
78
+
79
+ def add(path, score)
80
+ if should_record?(score)
81
+ @results << Result.new(path, score)
82
+ @results.sort_by!(&:score)
83
+ @results.pop if @results.size > @size
84
+ end
85
+ end
86
+ end
87
+
88
+ # Apps may have thousands of candidate templates so we attempt to
89
+ # generate the suggestions as efficiently as possible.
90
+ # First we split templates into prefixes and basenames, so that those can
91
+ # be matched separately.
92
+ def corrections
93
+ candidates = paths.flat_map(&:all_template_paths).uniq
94
+
95
+ if partial
96
+ candidates.select!(&:partial?)
97
+ else
98
+ candidates.reject!(&:partial?)
99
+ end
100
+
101
+ # Group by possible prefixes
102
+ files_by_dir = candidates.group_by(&:prefix)
103
+ files_by_dir.transform_values! do |files|
104
+ files.map do |file|
105
+ # Remove prefix
106
+ File.basename(file.to_s)
107
+ end
108
+ end
109
+
110
+ # No suggestions if there's an exact match, but wrong details
111
+ if prefixes.any? { |prefix| files_by_dir[prefix]&.include?(path) }
112
+ return []
113
+ end
114
+
115
+ cached_distance = Hash.new do |h, args|
116
+ h[args] = -DidYouMean::Jaro.distance(*args)
117
+ end
118
+
119
+ results = Results.new(6)
120
+
121
+ files_by_dir.keys.index_with do |dirname|
122
+ prefixes.map do |prefix|
123
+ cached_distance[[prefix, dirname]]
124
+ end.min
125
+ end.sort_by(&:last).each do |dirname, dirweight|
126
+ # If our directory's score makes it impossible to find a better match
127
+ # we can prune this search branch.
128
+ next unless results.should_record?(dirweight - 1.0)
129
+
130
+ files = files_by_dir[dirname]
131
+
132
+ files.each do |file|
133
+ fileweight = cached_distance[[path, file]]
134
+ score = dirweight + fileweight
135
+
136
+ results.add(File.join(dirname, file), score)
137
+ end
138
+ end
139
+
140
+ if partial
141
+ results.to_a.map { |res| res.sub(%r{_([^/]+)\z}, "\\1") }
142
+ else
143
+ results.to_a
144
+ end
145
+ end
146
+ end
52
147
  end
53
148
 
54
149
  class Template
55
150
  # The Template::Error exception is raised when the compilation or rendering of the template
56
151
  # fails. This exception then gathers a bunch of intimate details and uses it to report a
57
152
  # precise exception message.
58
- class Error < ActionViewError #:nodoc:
153
+ class Error < ActionViewError # :nodoc:
59
154
  SOURCE_CODE_RADIUS = 3
60
155
 
61
156
  # Override to prevent #cause resetting during re-raise.
@@ -134,7 +229,7 @@ module ActionView
134
229
 
135
230
  TemplateError = Template::Error
136
231
 
137
- class SyntaxErrorInTemplate < TemplateError #:nodoc
232
+ class SyntaxErrorInTemplate < TemplateError # :nodoc:
138
233
  def initialize(template, offending_code_string)
139
234
  @offending_code_string = offending_code_string
140
235
  super(template)
@@ -16,6 +16,9 @@ module ActionView
16
16
  # Do not escape templates of these mime types.
17
17
  class_attribute :escape_ignore_list, default: ["text/plain"]
18
18
 
19
+ # Strip trailing newlines from rendered output
20
+ class_attribute :strip_trailing_newlines, default: false
21
+
19
22
  ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")
20
23
 
21
24
  def self.call(template, source)
@@ -45,6 +48,9 @@ module ActionView
45
48
  # Always make sure we return a String in the default_internal
46
49
  erb.encode!
47
50
 
51
+ # Strip trailing newlines from the template if enabled
52
+ erb.chomp! if strip_trailing_newlines
53
+
48
54
  options = {
49
55
  escape: (self.class.escape_ignore_list.include? template.type),
50
56
  trim: (self.class.erb_trim_mode == "-")
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module ActionView #:nodoc:
3
+ module ActionView # :nodoc:
4
4
  # = Action View Template Handlers
5
- class Template #:nodoc:
6
- module Handlers #:nodoc:
5
+ class Template # :nodoc:
6
+ module Handlers # :nodoc:
7
7
  autoload :Raw, "action_view/template/handlers/raw"
8
8
  autoload :ERB, "action_view/template/handlers/erb"
9
9
  autoload :Html, "action_view/template/handlers/html"
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module ActionView #:nodoc:
3
+ module ActionView # :nodoc:
4
4
  # = Action View HTML Template
5
- class Template #:nodoc:
6
- class HTML #:nodoc:
5
+ class Template # :nodoc:
6
+ class HTML # :nodoc:
7
7
  attr_reader :type
8
8
 
9
9
  def initialize(string, type)
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module ActionView #:nodoc:
4
- class Template #:nodoc:
5
- class Inline < Template #:nodoc:
3
+ module ActionView # :nodoc:
4
+ class Template # :nodoc:
5
+ class Inline < Template # :nodoc:
6
6
  # This finalizer is needed (and exactly with a proc inside another proc)
7
7
  # otherwise templates leak in development.
8
8
  Finalizer = proc do |method_name, mod| # :nodoc:
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module ActionView #:nodoc:
3
+ module ActionView # :nodoc:
4
4
  # = Action View RawFile Template
5
- class Template #:nodoc:
6
- class RawFile #:nodoc:
5
+ class Template # :nodoc:
6
+ class RawFile # :nodoc:
7
7
  attr_accessor :type, :format
8
8
 
9
9
  def initialize(filename)