actionview 6.0.0

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 (113) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +271 -0
  3. data/MIT-LICENSE +21 -0
  4. data/README.rdoc +40 -0
  5. data/lib/action_view.rb +98 -0
  6. data/lib/action_view/base.rb +312 -0
  7. data/lib/action_view/buffers.rb +67 -0
  8. data/lib/action_view/cache_expiry.rb +54 -0
  9. data/lib/action_view/context.rb +32 -0
  10. data/lib/action_view/dependency_tracker.rb +175 -0
  11. data/lib/action_view/digestor.rb +126 -0
  12. data/lib/action_view/flows.rb +76 -0
  13. data/lib/action_view/gem_version.rb +17 -0
  14. data/lib/action_view/helpers.rb +66 -0
  15. data/lib/action_view/helpers/active_model_helper.rb +55 -0
  16. data/lib/action_view/helpers/asset_tag_helper.rb +488 -0
  17. data/lib/action_view/helpers/asset_url_helper.rb +470 -0
  18. data/lib/action_view/helpers/atom_feed_helper.rb +205 -0
  19. data/lib/action_view/helpers/cache_helper.rb +271 -0
  20. data/lib/action_view/helpers/capture_helper.rb +216 -0
  21. data/lib/action_view/helpers/controller_helper.rb +36 -0
  22. data/lib/action_view/helpers/csp_helper.rb +26 -0
  23. data/lib/action_view/helpers/csrf_helper.rb +35 -0
  24. data/lib/action_view/helpers/date_helper.rb +1200 -0
  25. data/lib/action_view/helpers/debug_helper.rb +36 -0
  26. data/lib/action_view/helpers/form_helper.rb +2569 -0
  27. data/lib/action_view/helpers/form_options_helper.rb +896 -0
  28. data/lib/action_view/helpers/form_tag_helper.rb +920 -0
  29. data/lib/action_view/helpers/javascript_helper.rb +95 -0
  30. data/lib/action_view/helpers/number_helper.rb +456 -0
  31. data/lib/action_view/helpers/output_safety_helper.rb +70 -0
  32. data/lib/action_view/helpers/rendering_helper.rb +101 -0
  33. data/lib/action_view/helpers/sanitize_helper.rb +171 -0
  34. data/lib/action_view/helpers/tag_helper.rb +314 -0
  35. data/lib/action_view/helpers/tags.rb +44 -0
  36. data/lib/action_view/helpers/tags/base.rb +196 -0
  37. data/lib/action_view/helpers/tags/check_box.rb +66 -0
  38. data/lib/action_view/helpers/tags/checkable.rb +18 -0
  39. data/lib/action_view/helpers/tags/collection_check_boxes.rb +36 -0
  40. data/lib/action_view/helpers/tags/collection_helpers.rb +119 -0
  41. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +31 -0
  42. data/lib/action_view/helpers/tags/collection_select.rb +30 -0
  43. data/lib/action_view/helpers/tags/color_field.rb +27 -0
  44. data/lib/action_view/helpers/tags/date_field.rb +15 -0
  45. data/lib/action_view/helpers/tags/date_select.rb +74 -0
  46. data/lib/action_view/helpers/tags/datetime_field.rb +32 -0
  47. data/lib/action_view/helpers/tags/datetime_local_field.rb +21 -0
  48. data/lib/action_view/helpers/tags/datetime_select.rb +10 -0
  49. data/lib/action_view/helpers/tags/email_field.rb +10 -0
  50. data/lib/action_view/helpers/tags/file_field.rb +10 -0
  51. data/lib/action_view/helpers/tags/grouped_collection_select.rb +31 -0
  52. data/lib/action_view/helpers/tags/hidden_field.rb +10 -0
  53. data/lib/action_view/helpers/tags/label.rb +81 -0
  54. data/lib/action_view/helpers/tags/month_field.rb +15 -0
  55. data/lib/action_view/helpers/tags/number_field.rb +20 -0
  56. data/lib/action_view/helpers/tags/password_field.rb +14 -0
  57. data/lib/action_view/helpers/tags/placeholderable.rb +24 -0
  58. data/lib/action_view/helpers/tags/radio_button.rb +33 -0
  59. data/lib/action_view/helpers/tags/range_field.rb +10 -0
  60. data/lib/action_view/helpers/tags/search_field.rb +27 -0
  61. data/lib/action_view/helpers/tags/select.rb +43 -0
  62. data/lib/action_view/helpers/tags/tel_field.rb +10 -0
  63. data/lib/action_view/helpers/tags/text_area.rb +24 -0
  64. data/lib/action_view/helpers/tags/text_field.rb +34 -0
  65. data/lib/action_view/helpers/tags/time_field.rb +15 -0
  66. data/lib/action_view/helpers/tags/time_select.rb +10 -0
  67. data/lib/action_view/helpers/tags/time_zone_select.rb +22 -0
  68. data/lib/action_view/helpers/tags/translator.rb +39 -0
  69. data/lib/action_view/helpers/tags/url_field.rb +10 -0
  70. data/lib/action_view/helpers/tags/week_field.rb +15 -0
  71. data/lib/action_view/helpers/text_helper.rb +486 -0
  72. data/lib/action_view/helpers/translation_helper.rb +145 -0
  73. data/lib/action_view/helpers/url_helper.rb +676 -0
  74. data/lib/action_view/layouts.rb +433 -0
  75. data/lib/action_view/locale/en.yml +56 -0
  76. data/lib/action_view/log_subscriber.rb +96 -0
  77. data/lib/action_view/lookup_context.rb +316 -0
  78. data/lib/action_view/model_naming.rb +14 -0
  79. data/lib/action_view/path_set.rb +95 -0
  80. data/lib/action_view/railtie.rb +105 -0
  81. data/lib/action_view/record_identifier.rb +112 -0
  82. data/lib/action_view/renderer/abstract_renderer.rb +108 -0
  83. data/lib/action_view/renderer/partial_renderer.rb +563 -0
  84. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +103 -0
  85. data/lib/action_view/renderer/renderer.rb +68 -0
  86. data/lib/action_view/renderer/streaming_template_renderer.rb +105 -0
  87. data/lib/action_view/renderer/template_renderer.rb +108 -0
  88. data/lib/action_view/rendering.rb +171 -0
  89. data/lib/action_view/routing_url_for.rb +146 -0
  90. data/lib/action_view/tasks/cache_digests.rake +25 -0
  91. data/lib/action_view/template.rb +393 -0
  92. data/lib/action_view/template/error.rb +161 -0
  93. data/lib/action_view/template/handlers.rb +92 -0
  94. data/lib/action_view/template/handlers/builder.rb +25 -0
  95. data/lib/action_view/template/handlers/erb.rb +84 -0
  96. data/lib/action_view/template/handlers/erb/erubi.rb +87 -0
  97. data/lib/action_view/template/handlers/html.rb +11 -0
  98. data/lib/action_view/template/handlers/raw.rb +11 -0
  99. data/lib/action_view/template/html.rb +43 -0
  100. data/lib/action_view/template/inline.rb +22 -0
  101. data/lib/action_view/template/raw_file.rb +28 -0
  102. data/lib/action_view/template/resolver.rb +394 -0
  103. data/lib/action_view/template/sources.rb +13 -0
  104. data/lib/action_view/template/sources/file.rb +17 -0
  105. data/lib/action_view/template/text.rb +35 -0
  106. data/lib/action_view/template/types.rb +57 -0
  107. data/lib/action_view/test_case.rb +300 -0
  108. data/lib/action_view/testing/resolvers.rb +67 -0
  109. data/lib/action_view/unbound_template.rb +32 -0
  110. data/lib/action_view/version.rb +10 -0
  111. data/lib/action_view/view_paths.rb +129 -0
  112. data/lib/assets/compiled/rails-ujs.js +746 -0
  113. metadata +260 -0
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/enumerable"
4
+
5
+ module ActionView
6
+ # = Action View Errors
7
+ class ActionViewError < StandardError #:nodoc:
8
+ end
9
+
10
+ class EncodingError < StandardError #:nodoc:
11
+ end
12
+
13
+ class WrongEncodingError < EncodingError #:nodoc:
14
+ def initialize(string, encoding)
15
+ @string, @encoding = string, encoding
16
+ end
17
+
18
+ def message
19
+ @string.force_encoding(Encoding::ASCII_8BIT)
20
+ "Your template was not saved as valid #{@encoding}. Please " \
21
+ "either specify #{@encoding} as the encoding for your template " \
22
+ "in your text editor, or mark the template with its " \
23
+ "encoding by inserting the following as the first line " \
24
+ "of the template:\n\n# encoding: <name of correct encoding>.\n\n" \
25
+ "The source of your template was:\n\n#{@string}"
26
+ end
27
+ end
28
+
29
+ class MissingTemplate < ActionViewError #:nodoc:
30
+ attr_reader :path
31
+
32
+ def initialize(paths, path, prefixes, partial, details, *)
33
+ @path = path
34
+ prefixes = Array(prefixes)
35
+ template_type = if partial
36
+ "partial"
37
+ elsif /layouts/i.match?(path)
38
+ "layout"
39
+ else
40
+ "template"
41
+ end
42
+
43
+ if partial && path.present?
44
+ path = path.sub(%r{([^/]+)$}, "_\\1")
45
+ end
46
+ searched_paths = prefixes.map { |prefix| [prefix, path].join("/") }
47
+
48
+ out = "Missing #{template_type} #{searched_paths.join(", ")} with #{details.inspect}. Searched in:\n"
49
+ out += paths.compact.map { |p| " * #{p.to_s.inspect}\n" }.join
50
+ super out
51
+ end
52
+ end
53
+
54
+ class Template
55
+ # The Template::Error exception is raised when the compilation or rendering of the template
56
+ # fails. This exception then gathers a bunch of intimate details and uses it to report a
57
+ # precise exception message.
58
+ class Error < ActionViewError #:nodoc:
59
+ SOURCE_CODE_RADIUS = 3
60
+
61
+ # Override to prevent #cause resetting during re-raise.
62
+ attr_reader :cause
63
+
64
+ def initialize(template)
65
+ super($!.message)
66
+ set_backtrace($!.backtrace)
67
+ @cause = $!
68
+ @template, @sub_templates = template, nil
69
+ end
70
+
71
+ def file_name
72
+ @template.identifier
73
+ end
74
+
75
+ def sub_template_message
76
+ if @sub_templates
77
+ "Trace of template inclusion: " +
78
+ @sub_templates.collect(&:inspect).join(", ")
79
+ else
80
+ ""
81
+ end
82
+ end
83
+
84
+ def source_extract(indentation = 0, output = :console)
85
+ return unless num = line_number
86
+ num = num.to_i
87
+
88
+ source_code = @template.source.split("\n")
89
+
90
+ start_on_line = [ num - SOURCE_CODE_RADIUS - 1, 0 ].max
91
+ end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min
92
+
93
+ indent = end_on_line.to_s.size + indentation
94
+ return unless source_code = source_code[start_on_line..end_on_line]
95
+
96
+ formatted_code_for(source_code, start_on_line, indent, output)
97
+ end
98
+
99
+ def sub_template_of(template_path)
100
+ @sub_templates ||= []
101
+ @sub_templates << template_path
102
+ end
103
+
104
+ def line_number
105
+ @line_number ||=
106
+ if file_name
107
+ regexp = /#{Regexp.escape File.basename(file_name)}:(\d+)/
108
+ $1 if message =~ regexp || backtrace.find { |line| line =~ regexp }
109
+ end
110
+ end
111
+
112
+ def annotated_source_code
113
+ source_extract(4)
114
+ end
115
+
116
+ private
117
+
118
+ def source_location
119
+ if line_number
120
+ "on line ##{line_number} of "
121
+ else
122
+ "in "
123
+ end + file_name
124
+ end
125
+
126
+ def formatted_code_for(source_code, line_counter, indent, output)
127
+ start_value = (output == :html) ? {} : []
128
+ source_code.inject(start_value) do |result, line|
129
+ line_counter += 1
130
+ if output == :html
131
+ result.update(line_counter.to_s => "%#{indent}s %s\n" % ["", line])
132
+ else
133
+ result << "%#{indent}s: %s" % [line_counter, line]
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ TemplateError = Template::Error
141
+
142
+ class SyntaxErrorInTemplate < TemplateError #:nodoc
143
+ def initialize(template, offending_code_string)
144
+ @offending_code_string = offending_code_string
145
+ super(template)
146
+ end
147
+
148
+ def message
149
+ <<~MESSAGE
150
+ Encountered a syntax error while rendering template: check #{@offending_code_string}
151
+ MESSAGE
152
+ end
153
+
154
+ def annotated_source_code
155
+ @offending_code_string.split("\n").map.with_index(1) { |line, index|
156
+ indentation = " " * 4
157
+ "#{index}:#{indentation}#{line}"
158
+ }
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/deprecation"
4
+
5
+ module ActionView #:nodoc:
6
+ # = Action View Template Handlers
7
+ class Template #:nodoc:
8
+ module Handlers #:nodoc:
9
+ autoload :Raw, "action_view/template/handlers/raw"
10
+ autoload :ERB, "action_view/template/handlers/erb"
11
+ autoload :Html, "action_view/template/handlers/html"
12
+ autoload :Builder, "action_view/template/handlers/builder"
13
+
14
+ def self.extended(base)
15
+ base.register_default_template_handler :raw, Raw.new
16
+ base.register_template_handler :erb, ERB.new
17
+ base.register_template_handler :html, Html.new
18
+ base.register_template_handler :builder, Builder.new
19
+ base.register_template_handler :ruby, lambda { |_, source| source }
20
+ end
21
+
22
+ @@template_handlers = {}
23
+ @@default_template_handlers = nil
24
+
25
+ def self.extensions
26
+ @@template_extensions ||= @@template_handlers.keys
27
+ end
28
+
29
+ class LegacyHandlerWrapper < SimpleDelegator # :nodoc:
30
+ def call(view, source)
31
+ __getobj__.call(ActionView::Template::LegacyTemplate.new(view, source))
32
+ end
33
+ end
34
+
35
+ # Register an object that knows how to handle template files with the given
36
+ # extensions. This can be used to implement new template types.
37
+ # The handler must respond to +:call+, which will be passed the template
38
+ # and should return the rendered template as a String.
39
+ def register_template_handler(*extensions, handler)
40
+ params = if handler.is_a?(Proc)
41
+ handler.parameters
42
+ else
43
+ handler.method(:call).parameters
44
+ end
45
+
46
+ unless params.find_all { |type, _| type == :req || type == :opt }.length >= 2
47
+ ActiveSupport::Deprecation.warn <<~eowarn
48
+ Single arity template handlers are deprecated. Template handlers must
49
+ now accept two parameters, the view object and the source for the view object.
50
+ Change:
51
+ >> #{handler}.call(#{params.map(&:last).join(", ")})
52
+ To:
53
+ >> #{handler}.call(#{params.map(&:last).join(", ")}, source)
54
+ eowarn
55
+ handler = LegacyHandlerWrapper.new(handler)
56
+ end
57
+
58
+ raise(ArgumentError, "Extension is required") if extensions.empty?
59
+ extensions.each do |extension|
60
+ @@template_handlers[extension.to_sym] = handler
61
+ end
62
+ @@template_extensions = nil
63
+ end
64
+
65
+ # Opposite to register_template_handler.
66
+ def unregister_template_handler(*extensions)
67
+ extensions.each do |extension|
68
+ handler = @@template_handlers.delete extension.to_sym
69
+ @@default_template_handlers = nil if @@default_template_handlers == handler
70
+ end
71
+ @@template_extensions = nil
72
+ end
73
+
74
+ def template_handler_extensions
75
+ @@template_handlers.keys.map(&:to_s).sort
76
+ end
77
+
78
+ def registered_template_handler(extension)
79
+ extension && @@template_handlers[extension.to_sym]
80
+ end
81
+
82
+ def register_default_template_handler(extension, klass)
83
+ register_template_handler(extension, klass)
84
+ @@default_template_handlers = klass
85
+ end
86
+
87
+ def handler_for_extension(extension)
88
+ registered_template_handler(extension) || @@default_template_handlers
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ module Template::Handlers
5
+ class Builder
6
+ class_attribute :default_format, default: :xml
7
+
8
+ def call(template, source)
9
+ require_engine
10
+ "xml = ::Builder::XmlMarkup.new(:indent => 2);" \
11
+ "self.output_buffer = xml.target!;" +
12
+ source +
13
+ ";xml.target!;"
14
+ end
15
+
16
+ private
17
+ def require_engine # :doc:
18
+ @required ||= begin
19
+ require "builder"
20
+ true
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ class Template
5
+ module Handlers
6
+ class ERB
7
+ autoload :Erubi, "action_view/template/handlers/erb/erubi"
8
+
9
+ # Specify trim mode for the ERB compiler. Defaults to '-'.
10
+ # See ERB documentation for suitable values.
11
+ class_attribute :erb_trim_mode, default: "-"
12
+
13
+ # Default implementation used.
14
+ class_attribute :erb_implementation, default: Erubi
15
+
16
+ # Do not escape templates of these mime types.
17
+ class_attribute :escape_ignore_list, default: ["text/plain"]
18
+
19
+ [self, singleton_class].each do |base|
20
+ base.alias_method :escape_whitelist, :escape_ignore_list
21
+ base.alias_method :escape_whitelist=, :escape_ignore_list=
22
+
23
+ base.deprecate(
24
+ escape_whitelist: "use #escape_ignore_list instead",
25
+ :escape_whitelist= => "use #escape_ignore_list= instead"
26
+ )
27
+ end
28
+
29
+ ENCODING_TAG = Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")
30
+
31
+ def self.call(template, source)
32
+ new.call(template, source)
33
+ end
34
+
35
+ def supports_streaming?
36
+ true
37
+ end
38
+
39
+ def handles_encoding?
40
+ true
41
+ end
42
+
43
+ def call(template, source)
44
+ # First, convert to BINARY, so in case the encoding is
45
+ # wrong, we can still find an encoding tag
46
+ # (<%# encoding %>) inside the String using a regular
47
+ # expression
48
+ template_source = source.dup.force_encoding(Encoding::ASCII_8BIT)
49
+
50
+ erb = template_source.gsub(ENCODING_TAG, "")
51
+ encoding = $2
52
+
53
+ erb.force_encoding valid_encoding(source.dup, encoding)
54
+
55
+ # Always make sure we return a String in the default_internal
56
+ erb.encode!
57
+
58
+ self.class.erb_implementation.new(
59
+ erb,
60
+ escape: (self.class.escape_ignore_list.include? template.type),
61
+ trim: (self.class.erb_trim_mode == "-")
62
+ ).src
63
+ end
64
+
65
+ private
66
+
67
+ def valid_encoding(string, encoding)
68
+ # If a magic encoding comment was found, tag the
69
+ # String with this encoding. This is for a case
70
+ # where the original String was assumed to be,
71
+ # for instance, UTF-8, but a magic comment
72
+ # proved otherwise
73
+ string.force_encoding(encoding) if encoding
74
+
75
+ # If the String is valid, return the encoding we found
76
+ return string.encoding if string.valid_encoding?
77
+
78
+ # Otherwise, raise an exception
79
+ raise WrongEncodingError.new(string, string.encoding)
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "erubi"
4
+
5
+ module ActionView
6
+ class Template
7
+ module Handlers
8
+ class ERB
9
+ class Erubi < ::Erubi::Engine
10
+ # :nodoc: all
11
+ def initialize(input, properties = {})
12
+ @newline_pending = 0
13
+
14
+ # Dup properties so that we don't modify argument
15
+ properties = Hash[properties]
16
+ properties[:preamble] = ""
17
+ properties[:postamble] = "@output_buffer.to_s"
18
+ properties[:bufvar] = "@output_buffer"
19
+ properties[:escapefunc] = ""
20
+
21
+ super
22
+ end
23
+
24
+ def evaluate(action_view_erb_handler_context)
25
+ src = @src
26
+ view = Class.new(ActionView::Base) {
27
+ include action_view_erb_handler_context._routes.url_helpers
28
+ class_eval("define_method(:_template) { |local_assigns, output_buffer| #{src} }", defined?(@filename) ? @filename : "(erubi)", 0)
29
+ }.empty
30
+ view._run(:_template, nil, {}, ActionView::OutputBuffer.new)
31
+ end
32
+
33
+ private
34
+ def add_text(text)
35
+ return if text.empty?
36
+
37
+ if text == "\n"
38
+ @newline_pending += 1
39
+ else
40
+ src << "@output_buffer.safe_append='"
41
+ src << "\n" * @newline_pending if @newline_pending > 0
42
+ src << text.gsub(/['\\]/, '\\\\\&')
43
+ src << "'.freeze;"
44
+
45
+ @newline_pending = 0
46
+ end
47
+ end
48
+
49
+ BLOCK_EXPR = /\s*((\s+|\))do|\{)(\s*\|[^|]*\|)?\s*\Z/
50
+
51
+ def add_expression(indicator, code)
52
+ flush_newline_if_pending(src)
53
+
54
+ if (indicator == "==") || @escape
55
+ src << "@output_buffer.safe_expr_append="
56
+ else
57
+ src << "@output_buffer.append="
58
+ end
59
+
60
+ if BLOCK_EXPR.match?(code)
61
+ src << " " << code
62
+ else
63
+ src << "(" << code << ");"
64
+ end
65
+ end
66
+
67
+ def add_code(code)
68
+ flush_newline_if_pending(src)
69
+ super
70
+ end
71
+
72
+ def add_postamble(_)
73
+ flush_newline_if_pending(src)
74
+ super
75
+ end
76
+
77
+ def flush_newline_if_pending(src)
78
+ if @newline_pending > 0
79
+ src << "@output_buffer.safe_append='#{"\n" * @newline_pending}'.freeze;"
80
+ @newline_pending = 0
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end