/
template.rb
56 lines (45 loc) · 2 KB
/
template.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class Minimal::Template
autoload :FormBuilderProxy, 'minimal/template/form_builder_proxy'
autoload :Handler, 'minimal/template/handler'
autoload :TranslatedTags, 'minimal/template/translated_tags'
AUTO_BUFFER = %r(^render|^error_message_|_select$|tag$|_to$|[^l]_for$|debug) # TODO explicitely whitelist helpers that return tags
TAG_NAMES = %w(abbr a body div em fieldset h1 h2 h3 h4 h5 h6 head html img input label li
link ol option p pre script select span strong table thead tbody tfoot td title th tr ul dl dd dt di)
module Base
attr_accessor :view, :locals, :block
def initialize(view = nil)
@view, @locals, @_auto_buffer = view, {}, {}
view.assigns.each { |name, value| instance_variable_set(:"@#{name}", value) } if view
end
def _render(locals = nil, format = :html, &block)
@locals = locals || {}
self.block = lambda { |*args| self << block.call(*args) }
send(:"to_#{format}", &self.block)
view.output_buffer
end
TAG_NAMES.each do |name|
define_method(name) { |*args, &block| content_tag(name, *args, &block) }
end
def <<(output)
view.output_buffer << output << "\n".html_safe
end
alias :output :<<
def respond_to?(method, include_private = false)
view.respond_to?(method) || locals.key?(method) || view.instance_variable_defined?("@#{method}") || super
end
protected
def method_missing(method, *args, &block)
return locals[method] if locals.key?(method)
return call_view(method, *args, &block) if view.respond_to?(method)
super
end
def call_view(method, *args, &block)
buffer = args.last.delete(:_buffer) if args.last.is_a?(Hash)
view.send(method, *args, &block).tap { |result| self << result if !buffer.is_a?(FalseClass) && auto_buffer?(method) }
end
def auto_buffer?(method)
@_auto_buffer.key?(method) ? @_auto_buffer[method] : @_auto_buffer[method] = AUTO_BUFFER =~ method.to_s
end
end
include Base
end