sinatra-rack-3-commonlit 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Binary file
Binary file
@@ -0,0 +1,206 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sinatra
4
+ # A poor man's ActiveSupport::HashWithIndifferentAccess, with all the Rails-y
5
+ # stuff removed.
6
+ #
7
+ # Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are
8
+ # considered to be the same.
9
+ #
10
+ # rgb = Sinatra::IndifferentHash.new
11
+ #
12
+ # rgb[:black] = '#000000' # symbol assignment
13
+ # rgb[:black] # => '#000000' # symbol retrieval
14
+ # rgb['black'] # => '#000000' # string retrieval
15
+ #
16
+ # rgb['white'] = '#FFFFFF' # string assignment
17
+ # rgb[:white] # => '#FFFFFF' # symbol retrieval
18
+ # rgb['white'] # => '#FFFFFF' # string retrieval
19
+ #
20
+ # Internally, symbols are mapped to strings when used as keys in the entire
21
+ # writing interface (calling e.g. <tt>[]=</tt>, <tt>merge</tt>). This mapping
22
+ # belongs to the public interface. For example, given:
23
+ #
24
+ # hash = Sinatra::IndifferentHash.new(:a=>1)
25
+ #
26
+ # You are guaranteed that the key is returned as a string:
27
+ #
28
+ # hash.keys # => ["a"]
29
+ #
30
+ # Technically other types of keys are accepted:
31
+ #
32
+ # hash = Sinatra::IndifferentHash.new(:a=>1)
33
+ # hash[0] = 0
34
+ # hash # => { "a"=>1, 0=>0 }
35
+ #
36
+ # But this class is intended for use cases where strings or symbols are the
37
+ # expected keys and it is convenient to understand both as the same. For
38
+ # example the +params+ hash in Sinatra.
39
+ class IndifferentHash < Hash
40
+ def self.[](*args)
41
+ new.merge!(Hash[*args])
42
+ end
43
+
44
+ def initialize(*args)
45
+ args.map!(&method(:convert_value))
46
+
47
+ super(*args)
48
+ end
49
+
50
+ def default(*args)
51
+ args.map!(&method(:convert_key))
52
+
53
+ super(*args)
54
+ end
55
+
56
+ def default=(value)
57
+ super(convert_value(value))
58
+ end
59
+
60
+ def assoc(key)
61
+ super(convert_key(key))
62
+ end
63
+
64
+ def rassoc(value)
65
+ super(convert_value(value))
66
+ end
67
+
68
+ def fetch(key, *args)
69
+ args.map!(&method(:convert_value))
70
+
71
+ super(convert_key(key), *args)
72
+ end
73
+
74
+ def [](key)
75
+ super(convert_key(key))
76
+ end
77
+
78
+ def []=(key, value)
79
+ super(convert_key(key), convert_value(value))
80
+ end
81
+
82
+ alias store []=
83
+
84
+ def key(value)
85
+ super(convert_value(value))
86
+ end
87
+
88
+ def key?(key)
89
+ super(convert_key(key))
90
+ end
91
+
92
+ alias has_key? key?
93
+ alias include? key?
94
+ alias member? key?
95
+
96
+ def value?(value)
97
+ super(convert_value(value))
98
+ end
99
+
100
+ alias has_value? value?
101
+
102
+ def delete(key)
103
+ super(convert_key(key))
104
+ end
105
+
106
+ # Added in Ruby 2.3
107
+ def dig(key, *other_keys)
108
+ super(convert_key(key), *other_keys)
109
+ end
110
+
111
+ def fetch_values(*keys)
112
+ keys.map!(&method(:convert_key))
113
+
114
+ super(*keys)
115
+ end
116
+
117
+ def slice(*keys)
118
+ keys.map!(&method(:convert_key))
119
+
120
+ self.class[super(*keys)]
121
+ end
122
+
123
+ def values_at(*keys)
124
+ keys.map!(&method(:convert_key))
125
+
126
+ super(*keys)
127
+ end
128
+
129
+ def merge!(*other_hashes)
130
+ other_hashes.each do |other_hash|
131
+ if other_hash.is_a?(self.class)
132
+ super(other_hash)
133
+ else
134
+ other_hash.each_pair do |key, value|
135
+ key = convert_key(key)
136
+ value = yield(key, self[key], value) if block_given? && key?(key)
137
+ self[key] = convert_value(value)
138
+ end
139
+ end
140
+ end
141
+
142
+ self
143
+ end
144
+
145
+ alias update merge!
146
+
147
+ def merge(*other_hashes, &block)
148
+ dup.merge!(*other_hashes, &block)
149
+ end
150
+
151
+ def replace(other_hash)
152
+ super(other_hash.is_a?(self.class) ? other_hash : self.class[other_hash])
153
+ end
154
+
155
+ def transform_values(&block)
156
+ dup.transform_values!(&block)
157
+ end
158
+
159
+ def transform_values!
160
+ super
161
+ super(&method(:convert_value))
162
+ end
163
+
164
+ def transform_keys(&block)
165
+ dup.transform_keys!(&block)
166
+ end
167
+
168
+ def transform_keys!
169
+ super
170
+ super(&method(:convert_key))
171
+ end
172
+
173
+ def select(*args, &block)
174
+ return to_enum(:select) unless block_given?
175
+
176
+ dup.tap { |hash| hash.select!(*args, &block) }
177
+ end
178
+
179
+ def reject(*args, &block)
180
+ return to_enum(:reject) unless block_given?
181
+
182
+ dup.tap { |hash| hash.reject!(*args, &block) }
183
+ end
184
+
185
+ def compact
186
+ dup.tap(&:compact!)
187
+ end
188
+
189
+ private
190
+
191
+ def convert_key(key)
192
+ key.is_a?(Symbol) ? key.to_s : key
193
+ end
194
+
195
+ def convert_value(value)
196
+ case value
197
+ when Hash
198
+ value.is_a?(self.class) ? value : self.class[value]
199
+ when Array
200
+ value.map(&method(:convert_value))
201
+ else
202
+ value
203
+ end
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sinatra
4
+ PARAMS_CONFIG = {}
5
+
6
+ if ARGV.any?
7
+ require 'optparse'
8
+ parser = OptionParser.new do |op|
9
+ op.on('-p port', 'set the port (default is 4567)') { |val| PARAMS_CONFIG[:port] = Integer(val) }
10
+ op.on('-s server', 'specify rack server/handler') { |val| PARAMS_CONFIG[:server] = val }
11
+ op.on('-q', 'turn on quiet mode (default is off)') { PARAMS_CONFIG[:quiet] = true }
12
+ op.on('-x', 'turn on the mutex lock (default is off)') { PARAMS_CONFIG[:lock] = true }
13
+ op.on('-e env', 'set the environment (default is development)') do |val|
14
+ ENV['RACK_ENV'] = val
15
+ PARAMS_CONFIG[:environment] = val.to_sym
16
+ end
17
+ op.on('-o addr', "set the host (default is (env == 'development' ? 'localhost' : '0.0.0.0'))") do |val|
18
+ PARAMS_CONFIG[:bind] = val
19
+ end
20
+ end
21
+ begin
22
+ parser.parse!(ARGV.dup)
23
+ rescue StandardError => e
24
+ PARAMS_CONFIG[:optparse_error] = e
25
+ end
26
+ end
27
+
28
+ require 'sinatra/base'
29
+
30
+ class Application < Base
31
+ # we assume that the first file that requires 'sinatra' is the
32
+ # app_file. all other path related options are calculated based
33
+ # on this path by default.
34
+ set :app_file, caller_files.first || $0
35
+
36
+ set :run, proc { File.expand_path($0) == File.expand_path(app_file) }
37
+
38
+ if run? && ARGV.any?
39
+ error = PARAMS_CONFIG.delete(:optparse_error)
40
+ raise error if error
41
+
42
+ PARAMS_CONFIG.each { |k, v| set k, v }
43
+ end
44
+ end
45
+
46
+ remove_const(:PARAMS_CONFIG)
47
+ at_exit { Application.run! if $!.nil? && Application.run? }
48
+ end
49
+
50
+ # include would include the module in Object
51
+ # extend only extends the `main` object
52
+ extend Sinatra::Delegator
53
+
54
+ class Rack::Builder
55
+ include Sinatra::Delegator
56
+ end
@@ -0,0 +1,364 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rack/show_exceptions'
4
+
5
+ module Sinatra
6
+ # Sinatra::ShowExceptions catches all exceptions raised from the app it
7
+ # wraps. It shows a useful backtrace with the sourcefile and clickable
8
+ # context, the whole Rack environment and the request data.
9
+ #
10
+ # Be careful when you use this on public-facing sites as it could reveal
11
+ # information helpful to attackers.
12
+ class ShowExceptions < Rack::ShowExceptions
13
+ @@eats_errors = Object.new
14
+ def @@eats_errors.flush(*) end
15
+
16
+ def @@eats_errors.puts(*) end
17
+
18
+ def initialize(app)
19
+ @app = app
20
+ end
21
+
22
+ def call(env)
23
+ @app.call(env)
24
+ rescue Exception => e
25
+ errors = env['rack.errors']
26
+ env['rack.errors'] = @@eats_errors
27
+
28
+ if prefers_plain_text?(env)
29
+ content_type = 'text/plain'
30
+ body = dump_exception(e)
31
+ else
32
+ content_type = 'text/html'
33
+ body = pretty(env, e)
34
+ end
35
+
36
+ env['rack.errors'] = errors
37
+
38
+ [
39
+ 500,
40
+ {
41
+ 'content-type' => content_type,
42
+ 'content-length' => body.bytesize.to_s
43
+ },
44
+ [body]
45
+ ]
46
+ end
47
+
48
+ def template
49
+ TEMPLATE
50
+ end
51
+
52
+ private
53
+
54
+ def bad_request?(exception)
55
+ Sinatra::BadRequest === exception
56
+ end
57
+
58
+ def prefers_plain_text?(env)
59
+ Request.new(env).preferred_type('text/plain', 'text/html') != 'text/html' &&
60
+ [/curl/].index { |item| item =~ env['HTTP_USER_AGENT'] }
61
+ end
62
+
63
+ def frame_class(frame)
64
+ if frame.filename =~ %r{lib/sinatra.*\.rb}
65
+ 'framework'
66
+ elsif (defined?(Gem) && frame.filename.include?(Gem.dir)) ||
67
+ frame.filename =~ %r{/bin/(\w+)\z}
68
+ 'system'
69
+ else
70
+ 'app'
71
+ end
72
+ end
73
+
74
+ TEMPLATE = ERB.new <<-HTML # :nodoc:
75
+ <!DOCTYPE html>
76
+ <html>
77
+ <head>
78
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
79
+ <title><%=h exception.class %> at <%=h path %></title>
80
+
81
+ <script type="text/javascript">
82
+ //<!--
83
+ function toggle(id) {
84
+ var pre = document.getElementById("pre-" + id);
85
+ var post = document.getElementById("post-" + id);
86
+ var context = document.getElementById("context-" + id);
87
+
88
+ if (pre.style.display == 'block') {
89
+ pre.style.display = 'none';
90
+ post.style.display = 'none';
91
+ context.style.background = "none";
92
+ } else {
93
+ pre.style.display = 'block';
94
+ post.style.display = 'block';
95
+ context.style.background = "#fffed9";
96
+ }
97
+ }
98
+
99
+ function toggleBacktrace(){
100
+ var bt = document.getElementById("backtrace");
101
+ var toggler = document.getElementById("expando");
102
+
103
+ if (bt.className == 'condensed') {
104
+ bt.className = 'expanded';
105
+ toggler.innerHTML = "(condense)";
106
+ } else {
107
+ bt.className = 'condensed';
108
+ toggler.innerHTML = "(expand)";
109
+ }
110
+ }
111
+ //-->
112
+ </script>
113
+
114
+ <style type="text/css" media="screen">
115
+ * {margin: 0; padding: 0; border: 0; outline: 0;}
116
+ div.clear {clear: both;}
117
+ body {background: #EEEEEE; margin: 0; padding: 0;
118
+ font-family: 'Lucida Grande', 'Lucida Sans Unicode',
119
+ 'Garuda';}
120
+ code {font-family: 'Lucida Console', monospace;
121
+ font-size: 12px;}
122
+ li {height: 18px;}
123
+ ul {list-style: none; margin: 0; padding: 0;}
124
+ ol:hover {cursor: pointer;}
125
+ ol li {white-space: pre;}
126
+ #explanation {font-size: 12px; color: #666666;
127
+ margin: 20px 0 0 100px;}
128
+ /* WRAP */
129
+ #wrap {width: 1000px; background: #FFFFFF; margin: 0 auto;
130
+ padding: 30px 50px 20px 50px;
131
+ border-left: 1px solid #DDDDDD;
132
+ border-right: 1px solid #DDDDDD;}
133
+ /* HEADER */
134
+ #header {margin: 0 auto 25px auto;}
135
+ #header img {float: left;}
136
+ #header #summary {float: left; margin: 12px 0 0 20px; width:660px;
137
+ font-family: 'Lucida Grande', 'Lucida Sans Unicode';}
138
+ h1 {margin: 0; font-size: 36px; color: #981919;}
139
+ h2 {margin: 0; font-size: 22px; color: #333333;}
140
+ #header ul {margin: 0; font-size: 12px; color: #666666;}
141
+ #header ul li strong{color: #444444;}
142
+ #header ul li {display: inline; padding: 0 10px;}
143
+ #header ul li.first {padding-left: 0;}
144
+ #header ul li.last {border: 0; padding-right: 0;}
145
+ /* BODY */
146
+ #backtrace,
147
+ #get,
148
+ #post,
149
+ #cookies,
150
+ #rack {width: 980px; margin: 0 auto 10px auto;}
151
+ p#nav {float: right; font-size: 14px;}
152
+ /* BACKTRACE */
153
+ a#expando {float: left; padding-left: 5px; color: #666666;
154
+ font-size: 14px; text-decoration: none; cursor: pointer;}
155
+ a#expando:hover {text-decoration: underline;}
156
+ h3 {float: left; width: 100px; margin-bottom: 10px;
157
+ color: #981919; font-size: 14px; font-weight: bold;}
158
+ #nav a {color: #666666; text-decoration: none; padding: 0 5px;}
159
+ #backtrace li.frame-info {background: #f7f7f7; padding-left: 10px;
160
+ font-size: 12px; color: #333333;}
161
+ #backtrace ul {list-style-position: outside; border: 1px solid #E9E9E9;
162
+ border-bottom: 0;}
163
+ #backtrace ol {width: 920px; margin-left: 50px;
164
+ font: 10px 'Lucida Console', monospace; color: #666666;}
165
+ #backtrace ol li {border: 0; border-left: 1px solid #E9E9E9;
166
+ padding: 2px 0;}
167
+ #backtrace ol code {font-size: 10px; color: #555555; padding-left: 5px;}
168
+ #backtrace-ul li {border-bottom: 1px solid #E9E9E9; height: auto;
169
+ padding: 3px 0;}
170
+ #backtrace-ul .code {padding: 6px 0 4px 0;}
171
+ #backtrace.condensed .system,
172
+ #backtrace.condensed .framework {display:none;}
173
+ /* REQUEST DATA */
174
+ p.no-data {padding-top: 2px; font-size: 12px; color: #666666;}
175
+ table.req {width: 980px; text-align: left; font-size: 12px;
176
+ color: #666666; padding: 0; border-spacing: 0;
177
+ border: 1px solid #EEEEEE; border-bottom: 0;
178
+ border-left: 0;
179
+ clear:both}
180
+ table.req tr th {padding: 2px 10px; font-weight: bold;
181
+ background: #F7F7F7; border-bottom: 1px solid #EEEEEE;
182
+ border-left: 1px solid #EEEEEE;}
183
+ table.req tr td {padding: 2px 20px 2px 10px;
184
+ border-bottom: 1px solid #EEEEEE;
185
+ border-left: 1px solid #EEEEEE;}
186
+ /* HIDE PRE/POST CODE AT START */
187
+ .pre-context,
188
+ .post-context {display: none;}
189
+
190
+ table td.code {width:750px}
191
+ table td.code div {width:750px;overflow:hidden}
192
+ </style>
193
+ </head>
194
+ <body>
195
+ <div id="wrap">
196
+ <div id="header">
197
+ <img src="<%= env['SCRIPT_NAME'] %>/__sinatra__/500.png" alt="application error" height="161" width="313" />
198
+ <div id="summary">
199
+ <h1><strong><%=h exception.class %></strong> at <strong><%=h path %>
200
+ </strong></h1>
201
+ <h2><%=h exception.message %></h2>
202
+ <ul>
203
+ <li class="first"><strong>file:</strong> <code>
204
+ <%=h frames.first.filename.split("/").last %></code></li>
205
+ <li><strong>location:</strong> <code><%=h frames.first.function %>
206
+ </code></li>
207
+ <li class="last"><strong>line:
208
+ </strong> <%=h frames.first.lineno %></li>
209
+ </ul>
210
+ </div>
211
+ <div class="clear"></div>
212
+ </div>
213
+
214
+ <div id="backtrace" class='condensed'>
215
+ <h3>BACKTRACE</h3>
216
+ <p><a href="#" id="expando"
217
+ onclick="toggleBacktrace(); return false">(expand)</a></p>
218
+ <p id="nav"><strong>JUMP TO:</strong>
219
+ <% unless bad_request?(exception) %>
220
+ <a href="#get-info">GET</a>
221
+ <a href="#post-info">POST</a>
222
+ <% end %>
223
+ <a href="#cookie-info">COOKIES</a>
224
+ <a href="#env-info">ENV</a>
225
+ </p>
226
+ <div class="clear"></div>
227
+
228
+ <ul id="backtrace-ul">
229
+
230
+ <% id = 1 %>
231
+ <% frames.each do |frame| %>
232
+ <% if frame.context_line && frame.context_line != "#" %>
233
+
234
+ <li class="frame-info <%= frame_class(frame) %>">
235
+ <code><%=h frame.filename %></code> in
236
+ <code><strong><%=h frame.function %></strong></code>
237
+ </li>
238
+
239
+ <li class="code <%= frame_class(frame) %>">
240
+ <% if frame.pre_context %>
241
+ <ol start="<%=h frame.pre_context_lineno + 1 %>"
242
+ class="pre-context" id="pre-<%= id %>"
243
+ onclick="toggle(<%= id %>);">
244
+ <% frame.pre_context.each do |line| %>
245
+ <li class="pre-context-line"><code><%=h line %></code></li>
246
+ <% end %>
247
+ </ol>
248
+ <% end %>
249
+
250
+ <ol start="<%= frame.lineno %>" class="context" id="<%= id %>"
251
+ onclick="toggle(<%= id %>);">
252
+ <li class="context-line" id="context-<%= id %>"><code><%=
253
+ h frame.context_line %></code></li>
254
+ </ol>
255
+
256
+ <% if frame.post_context %>
257
+ <ol start="<%=h frame.lineno + 1 %>" class="post-context"
258
+ id="post-<%= id %>" onclick="toggle(<%= id %>);">
259
+ <% frame.post_context.each do |line| %>
260
+ <li class="post-context-line"><code><%=h line %></code></li>
261
+ <% end %>
262
+ </ol>
263
+ <% end %>
264
+ <div class="clear"></div>
265
+ </li>
266
+
267
+ <% end %>
268
+
269
+ <% id += 1 %>
270
+ <% end %>
271
+
272
+ </ul>
273
+ </div> <!-- /BACKTRACE -->
274
+
275
+ <% unless bad_request?(exception) %>
276
+ <div id="get">
277
+ <h3 id="get-info">GET</h3>
278
+ <% if req.GET and not req.GET.empty? %>
279
+ <table class="req">
280
+ <tr>
281
+ <th>Variable</th>
282
+ <th>Value</th>
283
+ </tr>
284
+ <% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %>
285
+ <tr>
286
+ <td><%=h key %></td>
287
+ <td class="code"><div><%=h val.inspect %></div></td>
288
+ </tr>
289
+ <% } %>
290
+ </table>
291
+ <% else %>
292
+ <p class="no-data">No GET data.</p>
293
+ <% end %>
294
+ <div class="clear"></div>
295
+ </div> <!-- /GET -->
296
+
297
+ <div id="post">
298
+ <h3 id="post-info">POST</h3>
299
+ <% if req.POST and not req.POST.empty? %>
300
+ <table class="req">
301
+ <tr>
302
+ <th>Variable</th>
303
+ <th>Value</th>
304
+ </tr>
305
+ <% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %>
306
+ <tr>
307
+ <td><%=h key %></td>
308
+ <td class="code"><div><%=h val.inspect %></div></td>
309
+ </tr>
310
+ <% } %>
311
+ </table>
312
+ <% else %>
313
+ <p class="no-data">No POST data.</p>
314
+ <% end %>
315
+ <div class="clear"></div>
316
+ </div> <!-- /POST -->
317
+ <% end %>
318
+
319
+ <div id="cookies">
320
+ <h3 id="cookie-info">COOKIES</h3>
321
+ <% unless req.cookies.empty? %>
322
+ <table class="req">
323
+ <tr>
324
+ <th>Variable</th>
325
+ <th>Value</th>
326
+ </tr>
327
+ <% req.cookies.each { |key, val| %>
328
+ <tr>
329
+ <td><%=h key %></td>
330
+ <td class="code"><div><%=h val.inspect %></div></td>
331
+ </tr>
332
+ <% } %>
333
+ </table>
334
+ <% else %>
335
+ <p class="no-data">No cookie data.</p>
336
+ <% end %>
337
+ <div class="clear"></div>
338
+ </div> <!-- /COOKIES -->
339
+
340
+ <div id="rack">
341
+ <h3 id="env-info">Rack ENV</h3>
342
+ <table class="req">
343
+ <tr>
344
+ <th>Variable</th>
345
+ <th>Value</th>
346
+ </tr>
347
+ <% env.sort_by { |k, v| k.to_s }.each { |key, val| %>
348
+ <tr>
349
+ <td><%=h key %></td>
350
+ <td class="code"><div><%=h val %></div></td>
351
+ </tr>
352
+ <% } %>
353
+ </table>
354
+ <div class="clear"></div>
355
+ </div> <!-- /RACK ENV -->
356
+
357
+ <p id="explanation">You're seeing this error because you have
358
+ enabled the <code>show_exceptions</code> setting.</p>
359
+ </div> <!-- /WRAP -->
360
+ </body>
361
+ </html>
362
+ HTML
363
+ end
364
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sinatra
4
+ VERSION = '4.0.0.alpha'
5
+ end
data/lib/sinatra.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sinatra/main'
4
+
5
+ enable :inline_templates
data/sinatra.gemspec ADDED
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ version = File.read(File.expand_path('VERSION', __dir__)).strip
4
+
5
+ Gem::Specification.new 'sinatra-rack-3-commonlit', version do |s|
6
+ s.description = 'Sinatra is a DSL for quickly creating web applications in Ruby with minimal effort.'
7
+ s.summary = 'Classy web-development dressed in a DSL'
8
+ s.authors = ['Blake Mizerany', 'Ryan Tomayko', 'Simon Rozet', 'Konstantin Haase']
9
+ s.email = 'sinatrarb@googlegroups.com'
10
+ s.homepage = 'http://sinatrarb.com/'
11
+ s.license = 'MIT'
12
+ s.files = Dir['README*.md', 'lib/**/*', 'examples/*'] + [
13
+ '.yardopts',
14
+ 'AUTHORS.md',
15
+ 'CHANGELOG.md',
16
+ 'CONTRIBUTING.md',
17
+ 'Gemfile',
18
+ 'LICENSE',
19
+ 'MAINTENANCE.md',
20
+ 'Rakefile',
21
+ 'SECURITY.md',
22
+ 'sinatra.gemspec',
23
+ 'VERSION'
24
+ ]
25
+ s.extra_rdoc_files = %w[README.md LICENSE]
26
+ s.rdoc_options = %w[--line-numbers --title Sinatra --main README.rdoc --encoding=UTF-8]
27
+
28
+ unless s.respond_to?(:metadata)
29
+ raise <<-WARN
30
+ RubyGems 2.0 or newer is required to protect against public gem pushes. You can update your rubygems version by running:
31
+ gem install rubygems-update
32
+ update_rubygems:
33
+ gem update --system
34
+ WARN
35
+ end
36
+
37
+ s.metadata = {
38
+ 'source_code_uri' => 'https://github.com/sinatra/sinatra',
39
+ 'changelog_uri' => 'https://github.com/sinatra/sinatra/blob/main/CHANGELOG.md',
40
+ 'homepage_uri' => 'http://sinatrarb.com/',
41
+ 'bug_tracker_uri' => 'https://github.com/sinatra/sinatra/issues',
42
+ 'mailing_list_uri' => 'http://groups.google.com/group/sinatrarb',
43
+ 'documentation_uri' => 'https://www.rubydoc.info/gems/sinatra'
44
+ }
45
+
46
+ s.required_ruby_version = '>= 2.6.0'
47
+
48
+ s.add_dependency 'mustermann', '~> 3.0'
49
+ s.add_dependency 'rack', '>= 3.0.0.beta1', '< 4'
50
+ s.add_dependency 'rackup', '>= 2.0.0', '< 3'
51
+ s.add_dependency 'rack-session', '>= 2.0.0', '< 3'
52
+ s.add_dependency 'rack-protection', version
53
+ s.add_dependency 'tilt', '~> 2.0'
54
+
55
+ s.add_development_dependency 'rack-test', '~> 2'
56
+ end