require 'sinatra/base'
module Sinatra
# = Sinatra::LinkHeader
#
# Sinatra::LinkHeader adds a set of helper methods to generate link
# HTML tags and their corresponding Link HTTP headers.
#
# == Usage
#
# Once you had set up the helpers in your application (see below), you will
# be able to call the following methods from inside your route handlers,
# filters and templates:
#
# +prefetch+::
# Sets the Link HTTP headers and returns HTML tags to prefetch the given
# resources.
#
# +stylesheet+::
# Sets the Link HTTP headers and returns HTML tags to use the given
# stylesheets.
#
# +link+::
# Sets the Link HTTP headers and returns the corresponding HTML tags
# for the given resources.
#
# +link_headers+::
# Returns the corresponding HTML tags for the current Link HTTP headers.
#
# === Classic Application
#
# In a classic application simply require the helpers, and start using them:
#
# require "sinatra"
# require "sinatra/link_header"
#
# # The rest of your classic application code goes here...
#
# === Modular Application
#
# In a modular application you need to require the helpers, and then tell
# the application you will use them:
#
# require "sinatra/base"
# require "sinatra/link_header"
#
# class MyApp < Sinatra::Base
# helpers Sinatra::LinkHeader
#
# # The rest of your modular application code goes here...
# end
#
module LinkHeader
##
# Sets Link HTTP header and returns HTML tags for telling the browser to
# prefetch given resources (only supported by Opera and Firefox at the
# moment).
def prefetch(*urls)
link(:prefetch, *urls)
end
##
# Sets Link HTTP header and returns HTML tags for using stylesheets.
def stylesheet(*urls)
urls << {} unless urls.last.respond_to? :to_hash
urls.last[:type] ||= mime_type(:css)
link(:stylesheet, *urls)
end
##
# Sets Link HTTP header and returns corresponding HTML tags.
#
# Example:
#
# # Sets header:
# # Link: ; rel="next"
# # Returns String:
# # ''
# link '/foo', :rel => :next
#
# # Multiple URLs
# link :stylesheet, '/a.css', '/b.css'
def link(*urls)
opts = urls.last.respond_to?(:to_hash) ? urls.pop : {}
opts[:rel] = urls.shift unless urls.first.respond_to? :to_str
options = opts.map { |k, v| " #{k}=#{v.to_s.inspect}" }
html_pattern = ""
http_pattern = ["<%s>", *options].join ";"
link = (response["Link"] ||= "")
urls.map do |url|
link << "\n" unless link.empty?
link << (http_pattern % url)
html_pattern % url
end.join "\n"
end
##
# Takes the current value of th Link header(s) and generates HTML tags
# from it.
#
# Example:
#
# get '/' do
# # You can of course use fancy helpers like #link, #stylesheet
# # or #prefetch
# response["Link"] = '; rel="next"'
# haml :some_page
# end
#
# __END__
#
# @@ layout
# %head= link_headers
# %body= yield
def link_headers
yield if block_given?
return "" unless response.include? "Link"
response["Link"].lines.map do |line|
url, *opts = line.split(';').map(&:strip)
""
end.join "\n"
end
def self.registered(base)
puts "WARNING: #{self} is a helpers module, not an extension."
end
end
helpers LinkHeader
end