rack-server-pages 0.0.6 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +2 -0
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +96 -0
- data/.travis.yml +10 -4
- data/CHANGES.md +20 -1
- data/Gemfile +32 -46
- data/Guardfile +2 -2
- data/LICENSE.md +22 -0
- data/README.md +263 -187
- data/Rakefile +7 -6
- data/config.ru +3 -3
- data/lib/rack-server-pages/version.rb +1 -1
- data/lib/rack/server_pages.rb +37 -49
- data/lib/rack/server_pages/php_helper.rb +1 -1
- data/public/_layout.html.erb +1 -1
- data/public/rack_logo.png +0 -0
- data/public/rack_logo@2x.png +0 -0
- data/rack-server-pages.gemspec +13 -12
- data/spec/integration_spec.rb +34 -0
- data/spec/lib/rack/server_pages_spec.rb +17 -11
- data/spec/spec_helper.rb +26 -7
- data/views/examples/_layout.html.erb +1 -1
- data/views/examples/builder.xml.builder +2 -0
- data/views/examples/nokogiri.xml.nokogiri +1 -0
- data/views/examples/robots.txt +1 -0
- data/views/examples/source.html.slim +1 -1
- metadata +31 -21
data/Rakefile
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
|
-
require
|
3
|
+
require 'bundler/gem_tasks'
|
4
4
|
require 'rspec/core/rake_task'
|
5
5
|
|
6
|
-
|
6
|
+
desc 'Run all specs in spec directory'
|
7
|
+
RSpec::Core::RakeTask.new :spec
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
require 'rubocop/rake_task'
|
10
|
+
RuboCop::RakeTask.new
|
11
|
+
|
12
|
+
task default: [:rubocop, :spec]
|
data/config.ru
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
require 'bundler/setup'
|
3
|
-
|
3
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/lib'
|
4
4
|
require 'rack-server-pages'
|
5
5
|
|
6
6
|
# Tilt settings
|
@@ -9,7 +9,7 @@ require 'slim'
|
|
9
9
|
|
10
10
|
# .php as ERB template :)
|
11
11
|
Rack::ServerPages::Template::ERBTemplate.extensions << 'php' # ERBTemplate
|
12
|
-
#Rack::ServerPages::Template.use_tilt false
|
12
|
+
# Rack::ServerPages::Template.use_tilt false
|
13
13
|
Tilt.register Tilt::ERBTemplate, 'php' # TiltTemplate
|
14
14
|
|
15
15
|
module SampleHelper
|
@@ -26,7 +26,7 @@ module SampleHelper
|
|
26
26
|
end
|
27
27
|
|
28
28
|
run Rack::ServerPages.new { |config|
|
29
|
-
#config.show_exceptions = false
|
29
|
+
# config.show_exceptions = false
|
30
30
|
|
31
31
|
config.on_error do
|
32
32
|
response.body = ['Error!']
|
data/lib/rack/server_pages.rb
CHANGED
@@ -8,13 +8,12 @@ require 'forwardable'
|
|
8
8
|
|
9
9
|
module Rack
|
10
10
|
class ServerPages
|
11
|
-
|
12
11
|
class << self
|
13
12
|
def call(env)
|
14
13
|
new.call(env)
|
15
14
|
end
|
16
15
|
|
17
|
-
def [](options={}, &block)
|
16
|
+
def [](options = {}, &block)
|
18
17
|
new(nil, options, &block)
|
19
18
|
end
|
20
19
|
end
|
@@ -24,13 +23,13 @@ module Rack
|
|
24
23
|
yield @config if block_given?
|
25
24
|
@app = app || @config.failure_app || NotFound
|
26
25
|
|
27
|
-
require ::File.dirname(__FILE__) +
|
26
|
+
require ::File.dirname(__FILE__) + '/server_pages/php_helper'
|
28
27
|
@config.helpers Rack::ServerPages::PHPHelper
|
29
28
|
|
30
29
|
@config.filter.merge_from_helpers(@config.helpers)
|
31
30
|
@binding = Binding.extended_class(@config.helpers)
|
32
31
|
|
33
|
-
@path_regex = %r
|
32
|
+
@path_regex = %r{^#{@config.effective_path}/((?:[\w-]+/)+)?([A-z0-9][\w\.\-\@]*?\w)?(\.\w+)?$}
|
34
33
|
end
|
35
34
|
|
36
35
|
def call(env)
|
@@ -39,18 +38,18 @@ module Rack
|
|
39
38
|
|
40
39
|
def serving(env)
|
41
40
|
files = find_template_files(env['PATH_INFO'])
|
42
|
-
|
43
|
-
file = select_template_file(files)
|
44
|
-
(tpl = Template[file]) ? server_page(tpl) : StaticFile.new(file, @config.cache_control)
|
45
|
-
else
|
41
|
+
if files.nil? || files.empty?
|
46
42
|
@app
|
43
|
+
else
|
44
|
+
file = select_template_file(files)
|
45
|
+
(tpl = Template[file]) ? server_page(tpl) : File.new(file.split(env['PATH_INFO']).first)
|
47
46
|
end.call(env)
|
48
47
|
end
|
49
48
|
|
50
49
|
def find_template_files(path_info)
|
51
50
|
if m = path_info.match(@path_regex)
|
52
51
|
@config.view_paths.inject([]) do |files, path|
|
53
|
-
files.concat Dir["#{path}/#{m[1]}#{m[2]||'index'}#{m[3]}{.*,}"].select{|s|s.include?('.')}
|
52
|
+
files.concat Dir["#{path}/#{m[1]}#{m[2] || 'index'}#{m[3]}{.*,}"].select { |s| s.include?('.') }
|
54
53
|
end
|
55
54
|
end
|
56
55
|
end
|
@@ -80,7 +79,7 @@ module Rack
|
|
80
79
|
raise $!
|
81
80
|
else
|
82
81
|
scope.response.status = 500
|
83
|
-
scope.response['Content-Type'] ||=
|
82
|
+
scope.response['Content-Type'] ||= 'text/html'
|
84
83
|
@config.filter.invoke(scope, :on_error)
|
85
84
|
end
|
86
85
|
ensure
|
@@ -92,16 +91,16 @@ module Rack
|
|
92
91
|
end
|
93
92
|
|
94
93
|
class Filter
|
95
|
-
TYPES = [:before, :after, :on_error]
|
94
|
+
TYPES = [:before, :after, :on_error].freeze
|
96
95
|
TYPES.each do |type|
|
97
|
-
define_method(type) {|*fn, &block| add(type, *fn, &block) }
|
96
|
+
define_method(type) { |*fn, &block| add(type, *fn, &block) }
|
98
97
|
end
|
99
98
|
|
100
99
|
def initialize
|
101
|
-
@filters = Hash[[TYPES, Array.new(TYPES.size) {[]}].transpose]
|
100
|
+
@filters = Hash[[TYPES, Array.new(TYPES.size) { [] }].transpose]
|
102
101
|
end
|
103
102
|
|
104
|
-
def []
|
103
|
+
def [](type)
|
105
104
|
@filters[type]
|
106
105
|
end
|
107
106
|
|
@@ -163,14 +162,14 @@ module Rack
|
|
163
162
|
|
164
163
|
def show_exceptions?
|
165
164
|
if self[:show_exceptions].nil?
|
166
|
-
ENV['RACK_ENV'].nil?
|
165
|
+
ENV['RACK_ENV'].nil? || (ENV['RACK_ENV'] == 'development')
|
167
166
|
else
|
168
167
|
self[:show_exceptions]
|
169
168
|
end
|
170
169
|
end
|
171
170
|
|
172
171
|
def view_paths
|
173
|
-
(v = self[:view_path]).
|
172
|
+
(v = self[:view_path]).is_a?(Enumerable) ? v : [v.to_s]
|
174
173
|
end
|
175
174
|
|
176
175
|
def helpers(*args, &block)
|
@@ -181,9 +180,8 @@ module Rack
|
|
181
180
|
end
|
182
181
|
|
183
182
|
class Template
|
184
|
-
|
185
183
|
class << self
|
186
|
-
def []
|
184
|
+
def [](file)
|
187
185
|
engine.new(file).find_template
|
188
186
|
end
|
189
187
|
|
@@ -192,10 +190,10 @@ module Rack
|
|
192
190
|
end
|
193
191
|
|
194
192
|
def tilt?
|
195
|
-
@use_tilt.nil? ? (@use_tilt ||= !!defined?(Tilt)) : @use_tilt
|
193
|
+
@use_tilt.nil? ? (@use_tilt ||= !!defined?(Tilt)) : @use_tilt && defined?(Tilt)
|
196
194
|
end
|
197
195
|
|
198
|
-
def use_tilt
|
196
|
+
def use_tilt(bool = true)
|
199
197
|
@use_tilt = !!bool
|
200
198
|
end
|
201
199
|
end
|
@@ -212,16 +210,16 @@ module Rack
|
|
212
210
|
end
|
213
211
|
|
214
212
|
def mime_type_with_charset(charset = 'utf-8')
|
215
|
-
if (m = mime_type) =~ %r
|
216
|
-
|
213
|
+
if (m = mime_type) =~ %r{^(text/\w+|application/(?:javascript|(xhtml\+)?xml|json))$}
|
214
|
+
"#{m}; charset=#{charset}"
|
217
215
|
else
|
218
|
-
|
216
|
+
m
|
219
217
|
end
|
220
218
|
end
|
221
219
|
|
222
220
|
def render_with_layout(scope, locals = {}, &block)
|
223
|
-
content = render(scope, locals
|
224
|
-
if layout = scope.layout
|
221
|
+
content = render(scope, locals, &block)
|
222
|
+
if (layout = scope.layout) && (layout_file = Dir["#{layout}{.*,}"].first)
|
225
223
|
scope.layout(false)
|
226
224
|
Template[layout_file].render_with_layout(scope) { content }
|
227
225
|
else
|
@@ -231,7 +229,8 @@ module Rack
|
|
231
229
|
|
232
230
|
class TiltTemplate < Template
|
233
231
|
def find_template
|
234
|
-
|
232
|
+
@tilt ||= Tilt[@file]
|
233
|
+
@tilt ? self : nil
|
235
234
|
end
|
236
235
|
|
237
236
|
def render(scope, locals = {}, &block)
|
@@ -252,31 +251,20 @@ module Rack
|
|
252
251
|
end
|
253
252
|
|
254
253
|
def find_template
|
255
|
-
(@file =~ /\.(#{self.class.extensions.join('|')})$/)
|
254
|
+
(@file =~ /\.(#{self.class.extensions.join('|')})$/) && ::File.exist?(@file) ? self : nil
|
256
255
|
end
|
257
256
|
|
258
|
-
def render(scope,
|
257
|
+
def render(scope, _locals = {}, &block)
|
259
258
|
## TODO: support locals
|
260
259
|
ERB.new(IO.read(@file)).result(scope._binding(&block))
|
261
260
|
end
|
262
261
|
|
263
262
|
def default_mime_type
|
264
|
-
|
263
|
+
'text/html'
|
265
264
|
end
|
266
265
|
end
|
267
266
|
end
|
268
267
|
|
269
|
-
class StaticFile < File
|
270
|
-
def initialize(path, cache_control = nil)
|
271
|
-
@path = path
|
272
|
-
@cache_control = cache_control
|
273
|
-
end
|
274
|
-
|
275
|
-
def _call(env)
|
276
|
-
serving(env)
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
268
|
class NotFound
|
281
269
|
def self.[](file)
|
282
270
|
::File.file?(file) ? proc { Rack::Response.new([::File.read(file)], 404).finish } : self
|
@@ -288,13 +276,13 @@ module Rack
|
|
288
276
|
end
|
289
277
|
|
290
278
|
module CoreHelper
|
291
|
-
def redirect(target, status=302)
|
279
|
+
def redirect(target, status = 302)
|
292
280
|
response.redirect(target, status)
|
293
281
|
halt
|
294
282
|
end
|
295
283
|
|
296
284
|
def partial(file, locals = {}, &block)
|
297
|
-
if tpl_file = Dir["#{file}{.*,}"].first
|
285
|
+
if (tpl_file = Dir["#{file}{.*,}"].first) && (template = Template[tpl_file])
|
298
286
|
template.render(self, locals, &block)
|
299
287
|
else
|
300
288
|
IO.read(file)
|
@@ -307,18 +295,18 @@ module Rack
|
|
307
295
|
end
|
308
296
|
|
309
297
|
def halt(*args)
|
310
|
-
if args[0].
|
311
|
-
response.headers.merge! args[1] if (a1_is_h = args[1].
|
312
|
-
response.body = [
|
298
|
+
if args[0].is_a? Integer
|
299
|
+
response.headers.merge! args[1] if (a1_is_h = args[1].is_a? Hash)
|
300
|
+
response.body = [a1_is_h ? args[2] : args[1]]
|
313
301
|
response.status = args[0]
|
314
|
-
|
302
|
+
elsif args[0]
|
315
303
|
response.body = [args[0]]
|
316
304
|
end
|
317
305
|
throw :halt
|
318
306
|
end
|
319
307
|
|
320
|
-
def url(path =
|
321
|
-
env['SCRIPT_NAME'] + (path.to_s[0,1]!= '/' ? '/' : '') + path.to_s
|
308
|
+
def url(path = '')
|
309
|
+
env['SCRIPT_NAME'] + (path.to_s[0, 1] != '/' ? '/' : '') + path.to_s
|
322
310
|
end
|
323
311
|
end
|
324
312
|
|
@@ -347,7 +335,7 @@ module Rack
|
|
347
335
|
def initialize(env)
|
348
336
|
@request = Rack::Request.new(env)
|
349
337
|
@response = Rack::Response.new
|
350
|
-
@response['Content-Type'] = nil
|
338
|
+
# @response['Content-Type'] = nil
|
351
339
|
end
|
352
340
|
|
353
341
|
def _binding
|
@@ -59,7 +59,7 @@ module Rack::ServerPages::PHPHelper
|
|
59
59
|
<% if defined?(Tilt) %>
|
60
60
|
<h2>Tilt</h2>
|
61
61
|
<table border="0" cellpadding="3" width="600">
|
62
|
-
<% for key, value in Tilt.mappings do %>
|
62
|
+
<% for key, value in (Tilt.respond_to?(:mappings) ? Tilt.mappings : Tilt.lazy_map) do %>
|
63
63
|
<tr><td class="e"><%= key %></td><td class="v"><%= value %></td></tr>
|
64
64
|
<% end %>
|
65
65
|
</table>
|
data/public/_layout.html.erb
CHANGED
Binary file
|
Binary file
|
data/rack-server-pages.gemspec
CHANGED
@@ -1,23 +1,24 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require
|
2
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'rack-server-pages/version'
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
6
|
+
s.name = 'rack-server-pages'
|
7
7
|
s.version = Rack::ServerPages::VERSION
|
8
|
-
s.authors = [
|
9
|
-
s.email = [
|
10
|
-
s.homepage =
|
11
|
-
s.
|
12
|
-
s.
|
13
|
-
|
8
|
+
s.authors = ['Masato Igarashi', 'Daniel Doubrovkine']
|
9
|
+
s.email = ['m@igrs.jp']
|
10
|
+
s.homepage = 'http://github.com/migrs/rack-server-pages'
|
11
|
+
s.licenses = ['MIT']
|
12
|
+
s.summary = 'Rack middleware and appilcation for serving dynamic pages in very simple way.'
|
13
|
+
s.description = 'Rack middleware and appilcation for serving dynamic pages in very simple way.
|
14
|
+
There are no controllers and no models, just only views like a asp, jsp and php!'
|
14
15
|
|
15
|
-
#s.rubyforge_project = "rack-server-pages"
|
16
|
+
# s.rubyforge_project = "rack-server-pages"
|
16
17
|
|
17
18
|
s.files = `git ls-files`.split("\n")
|
18
19
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
-
s.require_paths = [
|
20
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
21
|
+
s.require_paths = ['lib']
|
21
22
|
|
22
23
|
s.add_dependency 'rack'
|
23
24
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
Capybara.app, = Rack::Builder.parse_file(File.expand_path('../../config.ru', __FILE__))
|
4
|
+
Capybara.current_driver = :selenium
|
5
|
+
|
6
|
+
describe 'Integration', js: true do
|
7
|
+
context 'root' do
|
8
|
+
before do
|
9
|
+
visit '/'
|
10
|
+
end
|
11
|
+
it 'loads homepage' do
|
12
|
+
expect(page.find('h1')).to have_content 'rack-server-pages'
|
13
|
+
end
|
14
|
+
it 'loads markdown README' do
|
15
|
+
click_link 'README'
|
16
|
+
expect(page.first('h1')).to have_content 'Rack Server Pages'
|
17
|
+
end
|
18
|
+
it 'rendered ERB' do
|
19
|
+
click_link 'sample.erb'
|
20
|
+
expect(page).to have_content 'PartAPartB'
|
21
|
+
end
|
22
|
+
it 'rendered PHP' do
|
23
|
+
click_link 'info.php'
|
24
|
+
expect(page).to have_content 'CGI/1.1'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
it 'renders all tilt examples' do
|
28
|
+
visit '/examples/'
|
29
|
+
page.all('body ul li a').map { |a| a['href'] }.each do |href|
|
30
|
+
puts href
|
31
|
+
visit href
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
2
|
begin
|
3
|
-
require 'ruby-debug'
|
4
|
-
require 'tapp'
|
3
|
+
require 'ruby-debug'
|
4
|
+
require 'tapp'
|
5
5
|
rescue LoadError
|
6
6
|
end
|
7
7
|
|
@@ -37,50 +37,56 @@ describe 'Rack::ServerPages' do
|
|
37
37
|
should_be_ok '/betty.css'
|
38
38
|
should_be_ok '/betty.css.sass'
|
39
39
|
end
|
40
|
+
|
41
|
+
context 'content-type: image/png' do
|
42
|
+
let(:content_type) { 'image/png' }
|
43
|
+
should_be_ok '/rack_logo.png'
|
44
|
+
should_be_ok '/rack_logo@2x.png'
|
45
|
+
end
|
40
46
|
end
|
41
47
|
|
42
48
|
describe 'Rack::ServerPages private methods' do
|
43
49
|
describe '#evalute_path_info' do
|
44
|
-
subject { m = app.new.instance_variable_get(:@path_regex).match(path_info); m[1,3] if m }
|
50
|
+
subject { m = app.new.instance_variable_get(:@path_regex).match(path_info); m[1, 3] if m }
|
45
51
|
|
46
52
|
context '/aaa/bbb.erb' do
|
47
53
|
let(:path_info) { '/aaa/bbb.erb' }
|
48
|
-
it {
|
54
|
+
it { is_expected.to eq %w(aaa/ bbb .erb) }
|
49
55
|
end
|
50
56
|
|
51
57
|
context '/aaa/bbb/ccc.erb' do
|
52
58
|
let(:path_info) { '/aaa/bbb/ccc.erb' }
|
53
|
-
it {
|
59
|
+
it { is_expected.to eq %w(aaa/bbb/ ccc .erb) }
|
54
60
|
end
|
55
61
|
|
56
62
|
context '/aaa/bbb/ccc.' do
|
57
63
|
let(:path_info) { '/aaa/bbb/ccc.' }
|
58
|
-
it {
|
64
|
+
it { is_expected.to be_nil }
|
59
65
|
end
|
60
66
|
|
61
67
|
context '/aaa/bbb/ccc' do
|
62
68
|
let(:path_info) { '/aaa/bbb/ccc' }
|
63
|
-
it {
|
69
|
+
it { is_expected.to eq ['aaa/bbb/', 'ccc', nil] }
|
64
70
|
end
|
65
71
|
|
66
72
|
context '/aaa-bbb/ccc' do
|
67
73
|
let(:path_info) { '/aaa-bbb/ccc' }
|
68
|
-
it {
|
74
|
+
it { is_expected.to eq ['aaa-bbb/', 'ccc', nil] }
|
69
75
|
end
|
70
76
|
|
71
77
|
context '/aaa/bbb/' do
|
72
78
|
let(:path_info) { '/aaa/bbb/' }
|
73
|
-
it {
|
79
|
+
it { is_expected.to eq ['aaa/bbb/', nil, nil] }
|
74
80
|
end
|
75
81
|
|
76
82
|
context '/' do
|
77
83
|
let(:path_info) { '/' }
|
78
|
-
it {
|
84
|
+
it { is_expected.to eq [nil, nil, nil] }
|
79
85
|
end
|
80
86
|
|
81
87
|
context path = '/aaa/bbb/AB-c.182-d.min.js' do
|
82
88
|
let(:path_info) { path }
|
83
|
-
it {
|
89
|
+
it { is_expected.to eq ['aaa/bbb/', 'AB-c.182-d.min', '.js'] }
|
84
90
|
end
|
85
91
|
end
|
86
92
|
end
|