actionview 4.1.0.beta1

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 (106) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +274 -0
  3. data/MIT-LICENSE +21 -0
  4. data/README.rdoc +34 -0
  5. data/lib/action_view.rb +97 -0
  6. data/lib/action_view/base.rb +205 -0
  7. data/lib/action_view/buffers.rb +49 -0
  8. data/lib/action_view/context.rb +36 -0
  9. data/lib/action_view/dependency_tracker.rb +93 -0
  10. data/lib/action_view/digestor.rb +116 -0
  11. data/lib/action_view/flows.rb +76 -0
  12. data/lib/action_view/helpers.rb +64 -0
  13. data/lib/action_view/helpers/active_model_helper.rb +49 -0
  14. data/lib/action_view/helpers/asset_tag_helper.rb +322 -0
  15. data/lib/action_view/helpers/asset_url_helper.rb +355 -0
  16. data/lib/action_view/helpers/atom_feed_helper.rb +203 -0
  17. data/lib/action_view/helpers/cache_helper.rb +200 -0
  18. data/lib/action_view/helpers/capture_helper.rb +216 -0
  19. data/lib/action_view/helpers/controller_helper.rb +25 -0
  20. data/lib/action_view/helpers/csrf_helper.rb +30 -0
  21. data/lib/action_view/helpers/date_helper.rb +1075 -0
  22. data/lib/action_view/helpers/debug_helper.rb +39 -0
  23. data/lib/action_view/helpers/form_helper.rb +1876 -0
  24. data/lib/action_view/helpers/form_options_helper.rb +843 -0
  25. data/lib/action_view/helpers/form_tag_helper.rb +746 -0
  26. data/lib/action_view/helpers/javascript_helper.rb +75 -0
  27. data/lib/action_view/helpers/number_helper.rb +425 -0
  28. data/lib/action_view/helpers/output_safety_helper.rb +38 -0
  29. data/lib/action_view/helpers/record_tag_helper.rb +108 -0
  30. data/lib/action_view/helpers/rendering_helper.rb +90 -0
  31. data/lib/action_view/helpers/sanitize_helper.rb +256 -0
  32. data/lib/action_view/helpers/tag_helper.rb +176 -0
  33. data/lib/action_view/helpers/tags.rb +41 -0
  34. data/lib/action_view/helpers/tags/base.rb +148 -0
  35. data/lib/action_view/helpers/tags/check_box.rb +64 -0
  36. data/lib/action_view/helpers/tags/checkable.rb +16 -0
  37. data/lib/action_view/helpers/tags/collection_check_boxes.rb +44 -0
  38. data/lib/action_view/helpers/tags/collection_helpers.rb +85 -0
  39. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +36 -0
  40. data/lib/action_view/helpers/tags/collection_select.rb +28 -0
  41. data/lib/action_view/helpers/tags/color_field.rb +25 -0
  42. data/lib/action_view/helpers/tags/date_field.rb +13 -0
  43. data/lib/action_view/helpers/tags/date_select.rb +72 -0
  44. data/lib/action_view/helpers/tags/datetime_field.rb +22 -0
  45. data/lib/action_view/helpers/tags/datetime_local_field.rb +19 -0
  46. data/lib/action_view/helpers/tags/datetime_select.rb +8 -0
  47. data/lib/action_view/helpers/tags/email_field.rb +8 -0
  48. data/lib/action_view/helpers/tags/file_field.rb +8 -0
  49. data/lib/action_view/helpers/tags/grouped_collection_select.rb +29 -0
  50. data/lib/action_view/helpers/tags/hidden_field.rb +8 -0
  51. data/lib/action_view/helpers/tags/label.rb +65 -0
  52. data/lib/action_view/helpers/tags/month_field.rb +13 -0
  53. data/lib/action_view/helpers/tags/number_field.rb +18 -0
  54. data/lib/action_view/helpers/tags/password_field.rb +12 -0
  55. data/lib/action_view/helpers/tags/radio_button.rb +31 -0
  56. data/lib/action_view/helpers/tags/range_field.rb +8 -0
  57. data/lib/action_view/helpers/tags/search_field.rb +24 -0
  58. data/lib/action_view/helpers/tags/select.rb +41 -0
  59. data/lib/action_view/helpers/tags/tel_field.rb +8 -0
  60. data/lib/action_view/helpers/tags/text_area.rb +18 -0
  61. data/lib/action_view/helpers/tags/text_field.rb +29 -0
  62. data/lib/action_view/helpers/tags/time_field.rb +13 -0
  63. data/lib/action_view/helpers/tags/time_select.rb +8 -0
  64. data/lib/action_view/helpers/tags/time_zone_select.rb +20 -0
  65. data/lib/action_view/helpers/tags/url_field.rb +8 -0
  66. data/lib/action_view/helpers/tags/week_field.rb +13 -0
  67. data/lib/action_view/helpers/text_helper.rb +447 -0
  68. data/lib/action_view/helpers/translation_helper.rb +111 -0
  69. data/lib/action_view/helpers/url_helper.rb +625 -0
  70. data/lib/action_view/layouts.rb +426 -0
  71. data/lib/action_view/locale/en.yml +56 -0
  72. data/lib/action_view/log_subscriber.rb +44 -0
  73. data/lib/action_view/lookup_context.rb +249 -0
  74. data/lib/action_view/model_naming.rb +12 -0
  75. data/lib/action_view/path_set.rb +77 -0
  76. data/lib/action_view/railtie.rb +49 -0
  77. data/lib/action_view/record_identifier.rb +84 -0
  78. data/lib/action_view/renderer/abstract_renderer.rb +47 -0
  79. data/lib/action_view/renderer/partial_renderer.rb +492 -0
  80. data/lib/action_view/renderer/renderer.rb +50 -0
  81. data/lib/action_view/renderer/streaming_template_renderer.rb +103 -0
  82. data/lib/action_view/renderer/template_renderer.rb +96 -0
  83. data/lib/action_view/rendering.rb +145 -0
  84. data/lib/action_view/routing_url_for.rb +109 -0
  85. data/lib/action_view/tasks/dependencies.rake +17 -0
  86. data/lib/action_view/template.rb +340 -0
  87. data/lib/action_view/template/error.rb +141 -0
  88. data/lib/action_view/template/handlers.rb +53 -0
  89. data/lib/action_view/template/handlers/builder.rb +26 -0
  90. data/lib/action_view/template/handlers/erb.rb +145 -0
  91. data/lib/action_view/template/handlers/raw.rb +11 -0
  92. data/lib/action_view/template/resolver.rb +329 -0
  93. data/lib/action_view/template/text.rb +34 -0
  94. data/lib/action_view/template/types.rb +57 -0
  95. data/lib/action_view/test_case.rb +272 -0
  96. data/lib/action_view/testing/resolvers.rb +50 -0
  97. data/lib/action_view/vendor/html-scanner.rb +20 -0
  98. data/lib/action_view/vendor/html-scanner/html/document.rb +68 -0
  99. data/lib/action_view/vendor/html-scanner/html/node.rb +532 -0
  100. data/lib/action_view/vendor/html-scanner/html/sanitizer.rb +188 -0
  101. data/lib/action_view/vendor/html-scanner/html/selector.rb +830 -0
  102. data/lib/action_view/vendor/html-scanner/html/tokenizer.rb +107 -0
  103. data/lib/action_view/vendor/html-scanner/html/version.rb +11 -0
  104. data/lib/action_view/version.rb +11 -0
  105. data/lib/action_view/view_paths.rb +96 -0
  106. metadata +218 -0
@@ -0,0 +1,34 @@
1
+ module ActionView #:nodoc:
2
+ # = Action View Text Template
3
+ class Template
4
+ class Text #:nodoc:
5
+ attr_accessor :type
6
+
7
+ def initialize(string, type = nil)
8
+ @string = string.to_s
9
+ @type = Types[type] || type if type
10
+ @type ||= Types[:text]
11
+ end
12
+
13
+ def identifier
14
+ 'text template'
15
+ end
16
+
17
+ def inspect
18
+ 'text template'
19
+ end
20
+
21
+ def to_str
22
+ @string
23
+ end
24
+
25
+ def render(*args)
26
+ to_str
27
+ end
28
+
29
+ def formats
30
+ [@type.to_sym]
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,57 @@
1
+ require 'set'
2
+ require 'active_support/core_ext/module/attribute_accessors'
3
+
4
+ module ActionView
5
+ class Template
6
+ class Types
7
+ class Type
8
+ cattr_accessor :types
9
+ self.types = Set.new
10
+
11
+ def self.register(*t)
12
+ types.merge(t.map { |type| type.to_s })
13
+ end
14
+
15
+ register :html, :text, :js, :css, :xml, :json
16
+
17
+ def self.[](type)
18
+ return type if type.is_a?(self)
19
+
20
+ if type.is_a?(Symbol) || types.member?(type.to_s)
21
+ new(type)
22
+ end
23
+ end
24
+
25
+ attr_reader :symbol
26
+
27
+ def initialize(symbol)
28
+ @symbol = symbol.to_sym
29
+ end
30
+
31
+ delegate :to_s, :to_sym, :to => :symbol
32
+ alias to_str to_s
33
+
34
+ def ref
35
+ to_sym || to_s
36
+ end
37
+
38
+ def ==(type)
39
+ return false if type.blank?
40
+ symbol.to_sym == type.to_sym
41
+ end
42
+ end
43
+
44
+ cattr_accessor :type_klass
45
+
46
+ def self.delegate_to(klass)
47
+ self.type_klass = klass
48
+ end
49
+
50
+ delegate_to Type
51
+
52
+ def self.[](type)
53
+ type_klass[type]
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,272 @@
1
+ require 'active_support/core_ext/module/remove_method'
2
+ require 'action_controller'
3
+ require 'action_controller/test_case'
4
+ require 'action_view'
5
+
6
+ module ActionView
7
+ # = Action View Test Case
8
+ class TestCase < ActiveSupport::TestCase
9
+ class TestController < ActionController::Base
10
+ include ActionDispatch::TestProcess
11
+
12
+ attr_accessor :request, :response, :params
13
+
14
+ class << self
15
+ attr_writer :controller_path
16
+ end
17
+
18
+ def controller_path=(path)
19
+ self.class.controller_path=(path)
20
+ end
21
+
22
+ def initialize
23
+ super
24
+ self.class.controller_path = ""
25
+ @request = ActionController::TestRequest.new
26
+ @response = ActionController::TestResponse.new
27
+
28
+ @request.env.delete('PATH_INFO')
29
+ @params = {}
30
+ end
31
+ end
32
+
33
+ module Behavior
34
+ extend ActiveSupport::Concern
35
+
36
+ include ActionDispatch::Assertions, ActionDispatch::TestProcess
37
+ include ActionController::TemplateAssertions
38
+ include ActionView::Context
39
+
40
+ include ActionDispatch::Routing::PolymorphicRoutes
41
+
42
+ include AbstractController::Helpers
43
+ include ActionView::Helpers
44
+ include ActionView::RecordIdentifier
45
+ include ActionView::RoutingUrlFor
46
+
47
+ include ActiveSupport::Testing::ConstantLookup
48
+
49
+ delegate :lookup_context, :to => :controller
50
+ attr_accessor :controller, :output_buffer, :rendered
51
+
52
+ module ClassMethods
53
+ def tests(helper_class)
54
+ case helper_class
55
+ when String, Symbol
56
+ self.helper_class = "#{helper_class.to_s.underscore}_helper".camelize.safe_constantize
57
+ when Module
58
+ self.helper_class = helper_class
59
+ end
60
+ end
61
+
62
+ def determine_default_helper_class(name)
63
+ determine_constant_from_test_name(name) do |constant|
64
+ Module === constant && !(Class === constant)
65
+ end
66
+ end
67
+
68
+ def helper_method(*methods)
69
+ # Almost a duplicate from ActionController::Helpers
70
+ methods.flatten.each do |method|
71
+ _helpers.module_eval <<-end_eval
72
+ def #{method}(*args, &block) # def current_user(*args, &block)
73
+ _test_case.send(%(#{method}), *args, &block) # _test_case.send(%(current_user), *args, &block)
74
+ end # end
75
+ end_eval
76
+ end
77
+ end
78
+
79
+ attr_writer :helper_class
80
+
81
+ def helper_class
82
+ @helper_class ||= determine_default_helper_class(name)
83
+ end
84
+
85
+ def new(*)
86
+ include_helper_modules!
87
+ super
88
+ end
89
+
90
+ private
91
+
92
+ def include_helper_modules!
93
+ helper(helper_class) if helper_class
94
+ include _helpers
95
+ end
96
+
97
+ end
98
+
99
+ def setup_with_controller
100
+ @controller = ActionView::TestCase::TestController.new
101
+ @request = @controller.request
102
+ @output_buffer = ActiveSupport::SafeBuffer.new
103
+ @rendered = ''
104
+
105
+ make_test_case_available_to_view!
106
+ say_no_to_protect_against_forgery!
107
+ end
108
+
109
+ def config
110
+ @controller.config if @controller.respond_to?(:config)
111
+ end
112
+
113
+ def render(options = {}, local_assigns = {}, &block)
114
+ view.assign(view_assigns)
115
+ @rendered << output = view.render(options, local_assigns, &block)
116
+ output
117
+ end
118
+
119
+ def rendered_views
120
+ @_rendered_views ||= RenderedViewsCollection.new
121
+ end
122
+
123
+ class RenderedViewsCollection
124
+ def initialize
125
+ @rendered_views ||= Hash.new { |hash, key| hash[key] = [] }
126
+ end
127
+
128
+ def add(view, locals)
129
+ @rendered_views[view] ||= []
130
+ @rendered_views[view] << locals
131
+ end
132
+
133
+ def locals_for(view)
134
+ @rendered_views[view]
135
+ end
136
+
137
+ def rendered_views
138
+ @rendered_views.keys
139
+ end
140
+
141
+ def view_rendered?(view, expected_locals)
142
+ locals_for(view).any? do |actual_locals|
143
+ expected_locals.all? {|key, value| value == actual_locals[key] }
144
+ end
145
+ end
146
+ end
147
+
148
+ included do
149
+ setup :setup_with_controller
150
+ end
151
+
152
+ private
153
+
154
+ # Support the selector assertions
155
+ #
156
+ # Need to experiment if this priority is the best one: rendered => output_buffer
157
+ def response_from_page
158
+ HTML::Document.new(@rendered.blank? ? @output_buffer : @rendered).root
159
+ end
160
+
161
+ def say_no_to_protect_against_forgery!
162
+ _helpers.module_eval do
163
+ remove_possible_method :protect_against_forgery?
164
+ def protect_against_forgery?
165
+ false
166
+ end
167
+ end
168
+ end
169
+
170
+ def make_test_case_available_to_view!
171
+ test_case_instance = self
172
+ _helpers.module_eval do
173
+ unless private_method_defined?(:_test_case)
174
+ define_method(:_test_case) { test_case_instance }
175
+ private :_test_case
176
+ end
177
+ end
178
+ end
179
+
180
+ module Locals
181
+ attr_accessor :rendered_views
182
+
183
+ def render(options = {}, local_assigns = {})
184
+ case options
185
+ when Hash
186
+ if block_given?
187
+ rendered_views.add options[:layout], options[:locals]
188
+ elsif options.key?(:partial)
189
+ rendered_views.add options[:partial], options[:locals]
190
+ end
191
+ else
192
+ rendered_views.add options, local_assigns
193
+ end
194
+
195
+ super
196
+ end
197
+ end
198
+
199
+ # The instance of ActionView::Base that is used by +render+.
200
+ def view
201
+ @view ||= begin
202
+ view = @controller.view_context
203
+ view.singleton_class.send :include, _helpers
204
+ view.extend(Locals)
205
+ view.rendered_views = self.rendered_views
206
+ view.output_buffer = self.output_buffer
207
+ view
208
+ end
209
+ end
210
+
211
+ alias_method :_view, :view
212
+
213
+ INTERNAL_IVARS = [
214
+ :@NAME,
215
+ :@failures,
216
+ :@assertions,
217
+ :@__io__,
218
+ :@_assertion_wrapped,
219
+ :@_assertions,
220
+ :@_result,
221
+ :@_routes,
222
+ :@controller,
223
+ :@_layouts,
224
+ :@_files,
225
+ :@_rendered_views,
226
+ :@method_name,
227
+ :@output_buffer,
228
+ :@_partials,
229
+ :@passed,
230
+ :@rendered,
231
+ :@request,
232
+ :@routes,
233
+ :@tagged_logger,
234
+ :@_templates,
235
+ :@options,
236
+ :@test_passed,
237
+ :@view,
238
+ :@view_context_class
239
+ ]
240
+
241
+ def _user_defined_ivars
242
+ instance_variables - INTERNAL_IVARS
243
+ end
244
+
245
+ # Returns a Hash of instance variables and their values, as defined by
246
+ # the user in the test case, which are then assigned to the view being
247
+ # rendered. This is generally intended for internal use and extension
248
+ # frameworks.
249
+ def view_assigns
250
+ Hash[_user_defined_ivars.map do |ivar|
251
+ [ivar[1..-1].to_sym, instance_variable_get(ivar)]
252
+ end]
253
+ end
254
+
255
+ def _routes
256
+ @controller._routes if @controller.respond_to?(:_routes)
257
+ end
258
+
259
+ def method_missing(selector, *args)
260
+ if @controller.respond_to?(:_routes) &&
261
+ ( @controller._routes.named_routes.helpers.include?(selector) ||
262
+ @controller._routes.mounted_helpers.method_defined?(selector) )
263
+ @controller.__send__(selector, *args)
264
+ else
265
+ super
266
+ end
267
+ end
268
+ end
269
+
270
+ include Behavior
271
+ end
272
+ end
@@ -0,0 +1,50 @@
1
+ require 'action_view/template/resolver'
2
+
3
+ module ActionView #:nodoc:
4
+ # Use FixtureResolver in your tests to simulate the presence of files on the
5
+ # file system. This is used internally by Rails' own test suite, and is
6
+ # useful for testing extensions that have no way of knowing what the file
7
+ # system will look like at runtime.
8
+ class FixtureResolver < PathResolver
9
+ attr_reader :hash
10
+
11
+ def initialize(hash = {}, pattern=nil)
12
+ super(pattern)
13
+ @hash = hash
14
+ end
15
+
16
+ def to_s
17
+ @hash.keys.join(', ')
18
+ end
19
+
20
+ private
21
+
22
+ def query(path, exts, formats)
23
+ query = ""
24
+ EXTENSIONS.each_key do |ext|
25
+ query << '(' << exts[ext].map {|e| e && Regexp.escape(".#{e}") }.join('|') << '|)'
26
+ end
27
+ query = /^(#{Regexp.escape(path)})#{query}$/
28
+
29
+ templates = []
30
+ @hash.each do |_path, array|
31
+ source, updated_at = array
32
+ next unless _path =~ query
33
+ handler, format = extract_handler_and_format(_path, formats)
34
+ templates << Template.new(source, _path, handler,
35
+ :virtual_path => path.virtual, :format => format, :updated_at => updated_at)
36
+ end
37
+
38
+ templates.sort_by {|t| -t.identifier.match(/^#{query}$/).captures.reject(&:blank?).size }
39
+ end
40
+ end
41
+
42
+ class NullResolver < PathResolver
43
+ def query(path, exts, formats)
44
+ handler, format = extract_handler_and_format(path, formats)
45
+ [ActionView::Template.new("Template generated by Null Resolver", path, handler, :virtual_path => path, :format => format)]
46
+ end
47
+ end
48
+
49
+ end
50
+
@@ -0,0 +1,20 @@
1
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/html-scanner"
2
+
3
+ module HTML
4
+ extend ActiveSupport::Autoload
5
+
6
+ eager_autoload do
7
+ autoload :CDATA, 'html/node'
8
+ autoload :Document, 'html/document'
9
+ autoload :FullSanitizer, 'html/sanitizer'
10
+ autoload :LinkSanitizer, 'html/sanitizer'
11
+ autoload :Node, 'html/node'
12
+ autoload :Sanitizer, 'html/sanitizer'
13
+ autoload :Selector, 'html/selector'
14
+ autoload :Tag, 'html/node'
15
+ autoload :Text, 'html/node'
16
+ autoload :Tokenizer, 'html/tokenizer'
17
+ autoload :Version, 'html/version'
18
+ autoload :WhiteListSanitizer, 'html/sanitizer'
19
+ end
20
+ end
@@ -0,0 +1,68 @@
1
+ require 'html/tokenizer'
2
+ require 'html/node'
3
+ require 'html/selector'
4
+ require 'html/sanitizer'
5
+
6
+ module HTML #:nodoc:
7
+ # A top-level HTML document. You give it a body of text, and it will parse that
8
+ # text into a tree of nodes.
9
+ class Document #:nodoc:
10
+
11
+ # The root of the parsed document.
12
+ attr_reader :root
13
+
14
+ # Create a new Document from the given text.
15
+ def initialize(text, strict=false, xml=false)
16
+ tokenizer = Tokenizer.new(text)
17
+ @root = Node.new(nil)
18
+ node_stack = [ @root ]
19
+ while token = tokenizer.next
20
+ node = Node.parse(node_stack.last, tokenizer.line, tokenizer.position, token, strict)
21
+
22
+ node_stack.last.children << node unless node.tag? && node.closing == :close
23
+ if node.tag?
24
+ if node_stack.length > 1 && node.closing == :close
25
+ if node_stack.last.name == node.name
26
+ if node_stack.last.children.empty?
27
+ node_stack.last.children << Text.new(node_stack.last, node.line, node.position, "")
28
+ end
29
+ node_stack.pop
30
+ else
31
+ open_start = node_stack.last.position - 20
32
+ open_start = 0 if open_start < 0
33
+ close_start = node.position - 20
34
+ close_start = 0 if close_start < 0
35
+ msg = <<EOF.strip
36
+ ignoring attempt to close #{node_stack.last.name} with #{node.name}
37
+ opened at byte #{node_stack.last.position}, line #{node_stack.last.line}
38
+ closed at byte #{node.position}, line #{node.line}
39
+ attributes at open: #{node_stack.last.attributes.inspect}
40
+ text around open: #{text[open_start,40].inspect}
41
+ text around close: #{text[close_start,40].inspect}
42
+ EOF
43
+ strict ? raise(msg) : warn(msg)
44
+ end
45
+ elsif !node.childless?(xml) && node.closing != :close
46
+ node_stack.push node
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ # Search the tree for (and return) the first node that matches the given
53
+ # conditions. The conditions are interpreted differently for different node
54
+ # types, see HTML::Text#find and HTML::Tag#find.
55
+ def find(conditions)
56
+ @root.find(conditions)
57
+ end
58
+
59
+ # Search the tree for (and return) all nodes that match the given
60
+ # conditions. The conditions are interpreted differently for different node
61
+ # types, see HTML::Text#find and HTML::Tag#find.
62
+ def find_all(conditions)
63
+ @root.find_all(conditions)
64
+ end
65
+
66
+ end
67
+
68
+ end