forked from sinatra/sinatra
/
link_header.rb
132 lines (124 loc) · 3.65 KB
/
link_header.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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
require 'sinatra/base'
module Sinatra
# = Sinatra::LinkHeader
#
# <tt>Sinatra::LinkHeader</tt> 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: </foo>; rel="next"
# # Returns String:
# # '<link href="/foo" rel="next" />'
# 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 = "<link href=\"%s\"#{options.join} />"
http_pattern = ['<%s>', *options].join ';'
link = (response['Link'] ||= '')
urls.map do |url|
link << "," unless link.empty?
link << (http_pattern % url)
html_pattern % url
end.join
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"] = '</foo>; 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'].split(",").map do |line|
url, *opts = line.split(';').map(&:strip)
"<link href=\"#{url[1..-2]}\" #{opts.join ' '} />"
end.join
end
def self.registered(_base)
puts "WARNING: #{self} is a helpers module, not an extension."
end
end
helpers LinkHeader
end