move capturing to its own extension

This commit is contained in:
Konstantin Haase 2011-04-22 23:04:13 +02:00
parent c4d55a1046
commit b280accec7
4 changed files with 55 additions and 25 deletions

View File

@ -0,0 +1,46 @@
require 'sinatra/base'
module Sinatra
module Capture
DUMMIES = {
Tilt::HamlTemplate => "!= capture_haml(*args, &block)",
Tilt::ERBTemplate => "<% yield(*args) %>",
Tilt::ErubisTemplate => "<%= yield(*args) %>",
:slim => "== yield(*args)"
}
def call!(env)
@current_engine = :ruby
super
end
def capture(options = {}, &block)
opts = { :block => block, :args => [] }.merge options
engine = opts.delete(:engine) || @current_engine
block = opts[:block]
if engine == :ruby
block[*opts[:args]]
else
dummy = DUMMIES[Tilt[engine]] || DUMMIES.fetch(engine)
eval '_buf.clear if defined? _buf', block.binding
render(engine, dummy, {}, opts, &block)
end
end
def capture_later(options = {}, &block)
opts = { :block => block, :args => [], :engine => @current_engine }
opts.merge options
end
private
def render(engine, *)
@current_engine, engine_was = engine.to_sym, @current_engine
super
ensure
@current_engine = engine_was
end
end
helpers Capture
end

View File

@ -1,4 +1,5 @@
require 'sinatra/base'
require 'sinatra/capture'
module Sinatra
##
@ -36,6 +37,8 @@ module Sinatra
# <tt>content_for</tt> setting the appropriate set of tags that should
# be added to the layout.
module ContentFor
include Capture
# Capture a block of content to be rendered later. For example:
#
# <% content_for :head do %>
@ -50,8 +53,7 @@ module Sinatra
# Your blocks can also receive values, which are passed to them
# by <tt>yield_content</tt>
def content_for(key, &block)
@current_engine ||= :ruby
content_blocks[key.to_sym] << [@current_engine, block]
content_blocks[key.to_sym] << capture_later(&block)
end
# Render the captured blocks for a given key. For example:
@ -72,33 +74,12 @@ module Sinatra
# Would pass <tt>1</tt> and <tt>2</tt> to all the blocks registered
# for <tt>:head</tt>.
def yield_content(key, *args)
content_blocks[key.to_sym].map { |e,b| capture(e, args, b) }.join
end
def self.capture
@capture ||= {}
opts = { :args => args }
content_blocks[key.to_sym].map { |c| capture c.merge(opts) }.join
end
private
# generated templates will be cached by Sinatra in production
capture[:haml] = "!= capture_haml(*args, &block)"
capture[:erb] = "<% yield(*args) %>"
capture[:erubis] = "<%= yield(*args) %>"
capture[:slim] = "== yield(*args)"
def capture(engine, args, block)
eval '_buf.clear if defined? _buf', block.binding
render(engine, Sinatra::ContentFor.capture.fetch(engine), {}, :args => args, :block => block, &block)
end
def render(engine, *)
@current_engine, engine_was = engine.to_sym, @current_engine
super
ensure
@current_engine = engine_was
end
def content_blocks
@content_blocks ||= Hash.new {|h,k| h[k] = [] }
end

View File

@ -11,6 +11,8 @@ module Sinatra
register :ConfigFile
register :Namespace
register :RespondWith
helpers :Capture
helpers :ContentFor
helpers :LinkHeader
end

View File

@ -28,6 +28,7 @@ Gem::Specification.new do |s|
"README.md",
"Rakefile",
"ideas.md",
"lib/sinatra/capture.rb",
"lib/sinatra/config_file.rb",
"lib/sinatra/content_for.rb",
"lib/sinatra/contrib.rb",