mirror of
https://github.com/sinatra/sinatra
synced 2023-03-27 23:18:01 -04:00
Merge branch 'content-for'
This commit is contained in:
commit
3eb5e41529
28 changed files with 251 additions and 0 deletions
20
sinatra-contrib/LICENSE
Normal file
20
sinatra-contrib/LICENSE
Normal file
|
@ -0,0 +1,20 @@
|
|||
Copyright (c) 2008-2011 Nicolas Sanguinetti, entp.com, Konstantin Haase
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
121
sinatra-contrib/lib/sinatra/content_for.rb
Normal file
121
sinatra-contrib/lib/sinatra/content_for.rb
Normal file
|
@ -0,0 +1,121 @@
|
|||
require 'sinatra/base'
|
||||
|
||||
module Sinatra
|
||||
##
|
||||
# Small extension for the Sinatra[http://sinatrarb.com] web framework
|
||||
# that allows you to use the following helpers in your views:
|
||||
#
|
||||
# <% content_for :some_key do %>
|
||||
# <chunk of="html">...</chunk>
|
||||
# <% end %>
|
||||
#
|
||||
# <%= yield_content :some_key %>
|
||||
#
|
||||
# This allows you to capture blocks inside views to be rendered later
|
||||
# in this request. For example, to populate different parts of your
|
||||
# layout from your view.
|
||||
#
|
||||
# When using this with the Haml rendering engine, you should do the
|
||||
# following:
|
||||
#
|
||||
# - content_for :some_key do
|
||||
# %chunk{ :of => "html" } ...
|
||||
#
|
||||
# = yield_content :some_key
|
||||
#
|
||||
# == Usage
|
||||
#
|
||||
# If you're writing "classic" style apps, then requring
|
||||
# <tt>sinatra/content_for</tt> should be enough. If you're writing
|
||||
# "classy" apps, then you also need to call
|
||||
# <tt>helpers Sinatra::ContentFor</tt> in your app definition.
|
||||
#
|
||||
# == And how is this useful?
|
||||
#
|
||||
# For example, some of your views might need a few javascript tags and
|
||||
# stylesheets, but you don't want to force this files in all your pages.
|
||||
# Then you can put <tt><% yield_content :scripts_and_styles %></tt> on
|
||||
# your layout, inside the <head> tag, and each view can call
|
||||
# <tt>content_for</tt> setting the appropriate set of tags that should
|
||||
# be added to the layout.
|
||||
#
|
||||
# == Credits
|
||||
#
|
||||
# Code by foca[http://github.com/foca], inspired on the Ruby on Rails
|
||||
# helpers with the same name. Haml support by mattly[http://github.com/mattly].
|
||||
module ContentFor
|
||||
# Capture a block of content to be rendered later. For example:
|
||||
#
|
||||
# <% content_for :head do %>
|
||||
# <script type="text/javascript" src="/foo.js"></script>
|
||||
# <% end %>
|
||||
#
|
||||
# You can call +content_for+ multiple times with the same key
|
||||
# (in the example +:head+), and when you render the blocks for
|
||||
# that key all of them will be rendered, in the same order you
|
||||
# captured them.
|
||||
#
|
||||
# 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]
|
||||
end
|
||||
|
||||
# Render the captured blocks for a given key. For example:
|
||||
#
|
||||
# <head>
|
||||
# <title>Example</title>
|
||||
# <%= yield_content :head %>
|
||||
# </head>
|
||||
#
|
||||
# Would render everything you declared with <tt>content_for
|
||||
# :head</tt> before closing the <tt><head></tt> tag.
|
||||
#
|
||||
# You can also pass values to the content blocks by passing them
|
||||
# as arguments after the key:
|
||||
#
|
||||
# <%= yield_content :head, 1, 2 %>
|
||||
#
|
||||
# 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(name, template = nil)
|
||||
@capture ||= {}
|
||||
@capture[name] = template if template
|
||||
@capture[name]
|
||||
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)
|
||||
@_out_buf, buf_was = nil, @_out_buf
|
||||
eval '_buf.clear if defined? _buf', block.binding
|
||||
render(engine, Sinatra::ContentFor.capture(engine), {}, :args => args, :block => block, &block)
|
||||
ensure
|
||||
@_out_buf = buf_was
|
||||
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
|
||||
end
|
||||
|
||||
helpers ContentFor
|
||||
end
|
|
@ -11,6 +11,7 @@ module Sinatra
|
|||
register :Decompile
|
||||
register :Namespace
|
||||
register :RespondWith
|
||||
helpers :ContentFor
|
||||
helpers :LinkHeader
|
||||
end
|
||||
|
||||
|
|
1
sinatra-contrib/spec/content_for/different_key.erb
Normal file
1
sinatra-contrib/spec/content_for/different_key.erb
Normal file
|
@ -0,0 +1 @@
|
|||
<% content_for :bar do %>bar<% end %>
|
1
sinatra-contrib/spec/content_for/different_key.erubis
Normal file
1
sinatra-contrib/spec/content_for/different_key.erubis
Normal file
|
@ -0,0 +1 @@
|
|||
<% content_for :bar do %>bar<% end %>
|
2
sinatra-contrib/spec/content_for/different_key.haml
Normal file
2
sinatra-contrib/spec/content_for/different_key.haml
Normal file
|
@ -0,0 +1,2 @@
|
|||
- content_for :bar do
|
||||
bar
|
2
sinatra-contrib/spec/content_for/different_key.slim
Normal file
2
sinatra-contrib/spec/content_for/different_key.slim
Normal file
|
@ -0,0 +1,2 @@
|
|||
- content_for :bar do
|
||||
| bar
|
1
sinatra-contrib/spec/content_for/layout.erb
Normal file
1
sinatra-contrib/spec/content_for/layout.erb
Normal file
|
@ -0,0 +1 @@
|
|||
<%= yield_content :foo %>
|
1
sinatra-contrib/spec/content_for/layout.erubis
Normal file
1
sinatra-contrib/spec/content_for/layout.erubis
Normal file
|
@ -0,0 +1 @@
|
|||
<%= yield_content :foo %>
|
1
sinatra-contrib/spec/content_for/layout.haml
Normal file
1
sinatra-contrib/spec/content_for/layout.haml
Normal file
|
@ -0,0 +1 @@
|
|||
= yield_content :foo
|
1
sinatra-contrib/spec/content_for/layout.slim
Normal file
1
sinatra-contrib/spec/content_for/layout.slim
Normal file
|
@ -0,0 +1 @@
|
|||
= yield_content :foo
|
4
sinatra-contrib/spec/content_for/multiple_blocks.erb
Normal file
4
sinatra-contrib/spec/content_for/multiple_blocks.erb
Normal file
|
@ -0,0 +1,4 @@
|
|||
<% content_for :foo do %>foo<% end %>
|
||||
<% content_for :foo do %>bar<% end %>
|
||||
<% content_for :baz do %>WON'T RENDER ME<% end %>
|
||||
<% content_for :foo do %>baz<% end %>
|
4
sinatra-contrib/spec/content_for/multiple_blocks.erubis
Normal file
4
sinatra-contrib/spec/content_for/multiple_blocks.erubis
Normal file
|
@ -0,0 +1,4 @@
|
|||
<% content_for :foo do %>foo<% end %>
|
||||
<% content_for :foo do %>bar<% end %>
|
||||
<% content_for :baz do %>WON'T RENDER ME<% end %>
|
||||
<% content_for :foo do %>baz<% end %>
|
8
sinatra-contrib/spec/content_for/multiple_blocks.haml
Normal file
8
sinatra-contrib/spec/content_for/multiple_blocks.haml
Normal file
|
@ -0,0 +1,8 @@
|
|||
- content_for :foo do
|
||||
foo
|
||||
- content_for :foo do
|
||||
bar
|
||||
- content_for :baz do
|
||||
WON'T RENDER ME
|
||||
- content_for :foo do
|
||||
baz
|
8
sinatra-contrib/spec/content_for/multiple_blocks.slim
Normal file
8
sinatra-contrib/spec/content_for/multiple_blocks.slim
Normal file
|
@ -0,0 +1,8 @@
|
|||
- content_for :foo do
|
||||
| foo
|
||||
- content_for :foo do
|
||||
| bar
|
||||
- content_for :baz do
|
||||
| WON'T RENDER ME
|
||||
- content_for :foo do
|
||||
| baz
|
1
sinatra-contrib/spec/content_for/passes_values.erb
Normal file
1
sinatra-contrib/spec/content_for/passes_values.erb
Normal file
|
@ -0,0 +1 @@
|
|||
<%= yield_content :foo, 1, 2 %>
|
1
sinatra-contrib/spec/content_for/passes_values.erubis
Normal file
1
sinatra-contrib/spec/content_for/passes_values.erubis
Normal file
|
@ -0,0 +1 @@
|
|||
<%= yield_content :foo, 1, 2 %>
|
1
sinatra-contrib/spec/content_for/passes_values.haml
Normal file
1
sinatra-contrib/spec/content_for/passes_values.haml
Normal file
|
@ -0,0 +1 @@
|
|||
= yield_content :foo, 1, 2
|
1
sinatra-contrib/spec/content_for/passes_values.slim
Normal file
1
sinatra-contrib/spec/content_for/passes_values.slim
Normal file
|
@ -0,0 +1 @@
|
|||
== yield_content :foo, 1, 2
|
1
sinatra-contrib/spec/content_for/same_key.erb
Normal file
1
sinatra-contrib/spec/content_for/same_key.erb
Normal file
|
@ -0,0 +1 @@
|
|||
<% content_for :foo do %>foo<% end %>
|
1
sinatra-contrib/spec/content_for/same_key.erubis
Normal file
1
sinatra-contrib/spec/content_for/same_key.erubis
Normal file
|
@ -0,0 +1 @@
|
|||
<% content_for :foo do %>foo<% end %>
|
2
sinatra-contrib/spec/content_for/same_key.haml
Normal file
2
sinatra-contrib/spec/content_for/same_key.haml
Normal file
|
@ -0,0 +1,2 @@
|
|||
- content_for :foo do
|
||||
foo
|
2
sinatra-contrib/spec/content_for/same_key.slim
Normal file
2
sinatra-contrib/spec/content_for/same_key.slim
Normal file
|
@ -0,0 +1,2 @@
|
|||
- content_for :foo do
|
||||
| foo
|
1
sinatra-contrib/spec/content_for/takes_values.erb
Normal file
1
sinatra-contrib/spec/content_for/takes_values.erb
Normal file
|
@ -0,0 +1 @@
|
|||
<% content_for :foo do |a, b| %><i><%= a %></i> <%= b %><% end %>
|
1
sinatra-contrib/spec/content_for/takes_values.erubis
Normal file
1
sinatra-contrib/spec/content_for/takes_values.erubis
Normal file
|
@ -0,0 +1 @@
|
|||
<% content_for :foo do |a, b| %><i><%= a %></i> <%= b %><% end %>
|
3
sinatra-contrib/spec/content_for/takes_values.haml
Normal file
3
sinatra-contrib/spec/content_for/takes_values.haml
Normal file
|
@ -0,0 +1,3 @@
|
|||
- content_for :foo do |a, b|
|
||||
%i= a
|
||||
=b
|
3
sinatra-contrib/spec/content_for/takes_values.slim
Normal file
3
sinatra-contrib/spec/content_for/takes_values.slim
Normal file
|
@ -0,0 +1,3 @@
|
|||
- content_for :foo do |a, b|
|
||||
i= a
|
||||
= b
|
57
sinatra-contrib/spec/content_for_spec.rb
Normal file
57
sinatra-contrib/spec/content_for_spec.rb
Normal file
|
@ -0,0 +1,57 @@
|
|||
require 'backports'
|
||||
require_relative 'spec_helper'
|
||||
|
||||
describe Sinatra::ContentFor do
|
||||
# TODO: liquid radius markaby builder nokogiri
|
||||
engines = %w[erb erubis haml slim]
|
||||
engines.each do |inner|
|
||||
engines.each do |outer|
|
||||
describe "#{inner.capitalize} templates with #{outer.capitalize} layouts" do
|
||||
def body
|
||||
super.gsub(/\s/, '')
|
||||
end
|
||||
|
||||
before :all do
|
||||
begin
|
||||
require inner
|
||||
require outer
|
||||
rescue LoadError => e
|
||||
pending "Skipping: " << e.message
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
mock_app do
|
||||
helpers Sinatra::ContentFor
|
||||
set inner, :layout_engine => outer
|
||||
set :views, File.expand_path("../content_for", __FILE__)
|
||||
get('/:view') { send(inner, params[:view].to_sym) }
|
||||
get('/:layout/:view') do
|
||||
send inner, params[:view].to_sym, :layout => params[:layout].to_sym
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'renders blocks declared with the same key you use when rendering' do
|
||||
get('/same_key').should be_ok
|
||||
body.should == "foo"
|
||||
end
|
||||
|
||||
it 'does not render a block with a different key' do
|
||||
get('/different_key').should be_ok
|
||||
body.should == ""
|
||||
end
|
||||
|
||||
it 'renders multiple blocks with the same key'do
|
||||
get('/multiple_blocks').should be_ok
|
||||
body.should == "foobarbaz"
|
||||
end
|
||||
|
||||
it 'passes values to the blocks' do
|
||||
get('/passes_values/takes_values').should be_ok
|
||||
body.should == "<i>1</i>2"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue