Skip to content
This repository has been archived by the owner on May 16, 2021. It is now read-only.

Commit

Permalink
move capturing to its own extension
Browse files Browse the repository at this point in the history
  • Loading branch information
rkh committed Apr 22, 2011
1 parent 6d8d4aa commit 8db79da
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 25 deletions.
46 changes: 46 additions & 0 deletions lib/sinatra/capture.rb
@@ -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
31 changes: 6 additions & 25 deletions lib/sinatra/content_for.rb
@@ -1,4 +1,5 @@
require 'sinatra/base'
require 'sinatra/capture'

module Sinatra
##
Expand Down Expand Up @@ -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 %>
Expand All @@ -50,8 +53,7 @@ module ContentFor
# 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:
Expand All @@ -72,33 +74,12 @@ def content_for(key, &block)
# 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
Expand Down
2 changes: 2 additions & 0 deletions lib/sinatra/contrib.rb
Expand Up @@ -11,6 +11,8 @@ module Common
register :ConfigFile
register :Namespace
register :RespondWith

helpers :Capture
helpers :ContentFor
helpers :LinkHeader
end
Expand Down
1 change: 1 addition & 0 deletions sinatra-contrib.gemspec
Expand Up @@ -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",
Expand Down

0 comments on commit 8db79da

Please sign in to comment.