rack-server-pages 0.0.6 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|