rail 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Guardfile +10 -0
- data/README.md +10 -12
- data/Rakefile +4 -7
- data/bin/rail +1 -1
- data/lib/rail.rb +7 -21
- data/lib/rail/application.rb +10 -82
- data/lib/rail/browser.rb +6 -10
- data/lib/rail/generator.rb +13 -20
- data/lib/rail/pipeline.rb +13 -13
- data/lib/rail/precompiler.rb +58 -0
- data/lib/rail/processor/base.rb +1 -1
- data/lib/rail/processor/coffee_script.rb +1 -1
- data/lib/rail/processor/haml.rb +2 -2
- data/lib/rail/request.rb +12 -2
- data/lib/rail/tasks/assets.rake +1 -1
- data/lib/rail/version.rb +1 -1
- data/lib/support/generator.rb +76 -0
- data/lib/support/inflector.rb +16 -0
- data/lib/support/loader.rb +55 -0
- data/lib/support/query_string.rb +8 -0
- data/lib/support/query_struct.rb +10 -0
- data/rail.gemspec +5 -0
- data/spec/{coffee_spec.rb → features/coffee_spec.rb} +5 -7
- data/spec/{haml_spec.rb → features/haml_spec.rb} +6 -8
- data/spec/{sass_spec.rb → features/sass_spec.rb} +5 -7
- data/spec/{project → fixtures/project}/app/assets/javascripts/application.js.coffee +0 -0
- data/spec/{project → fixtures/project}/app/assets/javascripts/font.coffee +0 -0
- data/spec/{project → fixtures/project}/app/assets/javascripts/parser.js.coffee +0 -0
- data/spec/{project → fixtures/project}/app/assets/stylesheets/_reset.scss +0 -0
- data/spec/{project → fixtures/project}/app/assets/stylesheets/application.css.scss +0 -0
- data/spec/{project → fixtures/project}/app/helpers/application_helper.rb +0 -0
- data/spec/{project → fixtures/project}/app/views/articles/about.html.haml +0 -0
- data/spec/{project → fixtures/project}/app/views/layouts/application.html.haml +0 -0
- data/spec/{project → fixtures/project}/app/views/layouts/articles.html.haml +0 -0
- data/spec/{project → fixtures/project}/config/application.rb +0 -0
- data/spec/{project → fixtures/project}/controller.rb +0 -0
- data/spec/lib/rail/application_spec.rb +38 -0
- data/spec/lib/rail/generator_spec.rb +14 -0
- data/spec/lib/rail/precompiler_spec.rb +25 -0
- data/spec/lib/rail/request_spec.rb +16 -0
- data/spec/lib/support/inflector_spec.rb +18 -0
- data/spec/lib/support/loader_spec.rb +61 -0
- data/spec/lib/support/query_string_spec.rb +11 -0
- data/spec/lib/support/query_struct_spec.rb +28 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/support/common_helper.rb +5 -0
- metadata +99 -32
- data/lib/generator.rb +0 -73
- data/lib/rail/support.rb +0 -7
data/lib/rail/processor/base.rb
CHANGED
data/lib/rail/processor/haml.rb
CHANGED
@@ -36,9 +36,9 @@ module Rail
|
|
36
36
|
private
|
37
37
|
|
38
38
|
def find_layout(filename)
|
39
|
-
asset = "layouts/#{
|
39
|
+
asset = "layouts/#{filename.split('/')[-2]}"
|
40
40
|
|
41
|
-
[
|
41
|
+
["#{asset}.haml", "#{asset}.html.haml"].each do |asset|
|
42
42
|
filename = pipeline.find(asset)
|
43
43
|
return filename if filename
|
44
44
|
end
|
data/lib/rail/request.rb
CHANGED
@@ -3,15 +3,25 @@ module Rail
|
|
3
3
|
attr_reader :env
|
4
4
|
|
5
5
|
def initialize(env)
|
6
|
-
@env = env
|
6
|
+
@env = rewrite(env)
|
7
7
|
end
|
8
8
|
|
9
9
|
def path
|
10
|
-
|
10
|
+
env['PATH_INFO']
|
11
11
|
end
|
12
12
|
|
13
13
|
def host
|
14
14
|
env['HTTP_HOST']
|
15
15
|
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def rewrite(env)
|
20
|
+
path = env['PATH_INFO']
|
21
|
+
path = '/index.html' if [nil, '', '/'].include?(path)
|
22
|
+
path = "#{path}.html" if File.extname(path).empty?
|
23
|
+
env['PATH_INFO'] = path
|
24
|
+
env
|
25
|
+
end
|
16
26
|
end
|
17
27
|
end
|
data/lib/rail/tasks/assets.rake
CHANGED
data/lib/rail/version.rb
CHANGED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Support
|
6
|
+
class Generator
|
7
|
+
attr_reader :destination, :source
|
8
|
+
|
9
|
+
def initialize(options)
|
10
|
+
@destination = options.fetch(:destination)
|
11
|
+
@source = options.fetch(:source)
|
12
|
+
end
|
13
|
+
|
14
|
+
def process(files, locals = {})
|
15
|
+
context = OpenStruct.new(locals)
|
16
|
+
files.each { |file| process_one(file, context) }
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def process_one(file, context)
|
22
|
+
output_file = find(file)
|
23
|
+
input_file = route(file)
|
24
|
+
|
25
|
+
directory = File.dirname(input_file)
|
26
|
+
unless File.directory?(directory)
|
27
|
+
report(directory)
|
28
|
+
make(directory)
|
29
|
+
end
|
30
|
+
|
31
|
+
report(input_file)
|
32
|
+
if template?(file)
|
33
|
+
dump(transform(load(output_file), context), input_file)
|
34
|
+
else
|
35
|
+
copy(output_file, input_file)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def template?(file)
|
40
|
+
File.extname(file) == '.erb'
|
41
|
+
end
|
42
|
+
|
43
|
+
def find(file)
|
44
|
+
File.join(source, file)
|
45
|
+
end
|
46
|
+
|
47
|
+
def route(file)
|
48
|
+
File.join(destination, file).gsub(/\.erb$/, '')
|
49
|
+
end
|
50
|
+
|
51
|
+
def report(message)
|
52
|
+
puts "Creating '#{ message }'..."
|
53
|
+
end
|
54
|
+
|
55
|
+
def make(directory)
|
56
|
+
FileUtils.mkdir_p(directory)
|
57
|
+
end
|
58
|
+
|
59
|
+
def copy(output_file, input_file)
|
60
|
+
FileUtils.cp(output_file, input_file)
|
61
|
+
end
|
62
|
+
|
63
|
+
def load(file)
|
64
|
+
File.read(file)
|
65
|
+
end
|
66
|
+
|
67
|
+
def dump(content, file)
|
68
|
+
File.open(file, 'w') { |file| file.write(content) }
|
69
|
+
end
|
70
|
+
|
71
|
+
def transform(content, context)
|
72
|
+
context.singleton_class.class_eval('def get_binding; binding; end')
|
73
|
+
ERB.new(content).result(context.get_binding)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Support
|
2
|
+
module Inflector
|
3
|
+
def self.titelize(name)
|
4
|
+
name.gsub(/[^\w ]/, '')
|
5
|
+
.gsub(/^[^a-zA-Z]+/, '')
|
6
|
+
.gsub(/_/, ' ')
|
7
|
+
.gsub(/ {2,}/, ' ')
|
8
|
+
.gsub(/ +$/, '')
|
9
|
+
.gsub(/^\w| \w/, &:upcase)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.modulize(name)
|
13
|
+
name.split(/[\s_]+/).map(&:capitalize).join.to_sym
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'support/inflector'
|
2
|
+
|
3
|
+
module Support
|
4
|
+
class Loader
|
5
|
+
def initialize(pattern)
|
6
|
+
@pattern = pattern
|
7
|
+
@files = []
|
8
|
+
@names = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def reload?
|
12
|
+
!last_scanned || !last_loaded || last_loaded < last_modified
|
13
|
+
end
|
14
|
+
|
15
|
+
def find
|
16
|
+
scan!
|
17
|
+
|
18
|
+
if reload?
|
19
|
+
unload!
|
20
|
+
load!
|
21
|
+
end
|
22
|
+
|
23
|
+
modules
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :pattern, :files, :names, :modules
|
29
|
+
attr_reader :last_scanned, :last_loaded
|
30
|
+
|
31
|
+
def scan!
|
32
|
+
@last_scanned = Time.now
|
33
|
+
@files = Dir[pattern]
|
34
|
+
end
|
35
|
+
|
36
|
+
def last_modified
|
37
|
+
files.map { |file| File.mtime(file) }.max || Time.at(0)
|
38
|
+
end
|
39
|
+
|
40
|
+
def unload!
|
41
|
+
names.each { |name| Object.send(:remove_const, name) }
|
42
|
+
names.clear
|
43
|
+
end
|
44
|
+
|
45
|
+
def load!
|
46
|
+
@names = files.map do |file|
|
47
|
+
load file
|
48
|
+
Support::Inflector.modulize(File.basename(file, '.rb'))
|
49
|
+
end
|
50
|
+
|
51
|
+
@modules = names.map { |name| Object.const_get(name) }
|
52
|
+
@last_loaded = last_scanned
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/rail.gemspec
CHANGED
@@ -33,4 +33,9 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_dependency 'uglifier', '~> 2.5'
|
34
34
|
|
35
35
|
spec.add_development_dependency 'bundler', '~> 1.6'
|
36
|
+
|
37
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
38
|
+
|
39
|
+
spec.add_development_dependency 'guard', '~> 2.6'
|
40
|
+
spec.add_development_dependency 'guard-rspec', '~> 4.3'
|
36
41
|
end
|
@@ -1,15 +1,13 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fixtures/project/controller'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
describe Rail::Application do
|
4
|
+
RSpec.describe Rail::Application do
|
7
5
|
it 'handles uncompressed CoffeeScript assets' do
|
8
6
|
controller = Controller.new do
|
9
7
|
config.compress = false
|
10
8
|
end
|
11
9
|
body = controller.process('/application.js')
|
12
|
-
|
10
|
+
expect(body.strip).to eq <<-BODY.strip
|
13
11
|
(function() {
|
14
12
|
window.Parser = (function() {
|
15
13
|
function Parser(format) {
|
@@ -46,7 +44,7 @@ describe Rail::Application do
|
|
46
44
|
config.compress = true
|
47
45
|
end
|
48
46
|
body = controller.process('/application.js')
|
49
|
-
|
47
|
+
expect(body.strip).to eq <<-BODY.strip
|
50
48
|
(function(){window.Parser=function(){function n(n){this.format=n}return n}()}).call(this),function(){window.Font=function(){function n(n){this.name=n}return n}()}.call(this),function(){var n;n=new Font(\"Benton Modern Display\")}.call(this);
|
51
49
|
BODY
|
52
50
|
end
|
@@ -1,15 +1,13 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fixtures/project/controller'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
describe Rail::Application do
|
4
|
+
RSpec.describe Rail::Application do
|
7
5
|
it 'handles uncompressed Haml assets' do
|
8
6
|
controller = Controller.new do
|
9
7
|
config.compress = false
|
10
8
|
end
|
11
9
|
body = controller.process('/')
|
12
|
-
|
10
|
+
expect(body.strip).to eq <<-BODY.strip
|
13
11
|
<!DOCTYPE html>
|
14
12
|
<html>
|
15
13
|
<head>
|
@@ -27,7 +25,7 @@ describe Rail::Application do
|
|
27
25
|
config.compress = true
|
28
26
|
end
|
29
27
|
body = controller.process('/')
|
30
|
-
|
28
|
+
expect(body.strip).to eq <<-BODY.strip
|
31
29
|
<!DOCTYPE html>
|
32
30
|
<html>
|
33
31
|
<head>
|
@@ -45,7 +43,7 @@ describe Rail::Application do
|
|
45
43
|
config.compress = false
|
46
44
|
end
|
47
45
|
body = controller.process('/articles/about')
|
48
|
-
|
46
|
+
expect(body.strip).to eq <<-BODY.strip
|
49
47
|
<!DOCTYPE html>
|
50
48
|
<html>
|
51
49
|
<head>
|
@@ -1,15 +1,13 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fixtures/project/controller'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
describe Rail::Application do
|
4
|
+
RSpec.describe Rail::Application do
|
7
5
|
it 'handles uncompressed Sass assests' do
|
8
6
|
controller = Controller.new do
|
9
7
|
config.compress = false
|
10
8
|
end
|
11
9
|
body = controller.process('/application.css')
|
12
|
-
|
10
|
+
expect(body.strip).to eq <<-BODY.strip
|
13
11
|
* {
|
14
12
|
margin: 0;
|
15
13
|
padding: 0; }
|
@@ -24,7 +22,7 @@ body {
|
|
24
22
|
config.compress = true
|
25
23
|
end
|
26
24
|
body = controller.process('/application.css')
|
27
|
-
|
25
|
+
expect(body.strip).to eq <<-BODY.strip
|
28
26
|
*{margin:0;padding:0}body{font-family:'Benton Modern Display'}
|
29
27
|
BODY
|
30
28
|
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fixtures/project/config/application'
|
3
|
+
|
4
|
+
RSpec.describe Rail::Application do
|
5
|
+
subject { Project::Application.new }
|
6
|
+
|
7
|
+
describe '#call' do
|
8
|
+
context 'when index.html exists' do
|
9
|
+
before do
|
10
|
+
allow(File).to receive(:exist?).and_return(true)
|
11
|
+
end
|
12
|
+
|
13
|
+
['/', '/index.html'].each do |path|
|
14
|
+
it "lets the browser serve #{path}" do
|
15
|
+
expect(subject.browser).to receive(:process)
|
16
|
+
expect(subject.pipeline).not_to receive(:process)
|
17
|
+
|
18
|
+
subject.call('PATH_INFO' => path)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when index.html does not exist' do
|
24
|
+
before do
|
25
|
+
allow(File).to receive(:exist?).and_return(false)
|
26
|
+
end
|
27
|
+
|
28
|
+
['/', '/index.html'].each do |path|
|
29
|
+
it "lets the pipeline serve #{path}" do
|
30
|
+
expect(subject.browser).not_to receive(:process)
|
31
|
+
expect(subject.pipeline).to receive(:process)
|
32
|
+
|
33
|
+
subject.call('PATH_INFO' => path)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rail/generator'
|
3
|
+
|
4
|
+
RSpec.describe Rail::Generator do
|
5
|
+
let(:destination) { 'project' }
|
6
|
+
subject { described_class.new(destination: destination) }
|
7
|
+
|
8
|
+
describe '#run' do
|
9
|
+
it 'raises an exception if the destination folder already exists' do
|
10
|
+
expect(File).to receive(:directory?).and_return(true)
|
11
|
+
expect { subject.run }.to raise_error(ArgumentError)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rail/request'
|
3
|
+
require 'rail/precompiler'
|
4
|
+
|
5
|
+
RSpec.describe Rail::Precompiler do
|
6
|
+
let(:pipeline) { double }
|
7
|
+
let(:storage) { double }
|
8
|
+
|
9
|
+
subject do
|
10
|
+
precompiler = described_class.new(pipeline, storage)
|
11
|
+
allow(precompiler).to receive(:report)
|
12
|
+
precompiler
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#process' do
|
16
|
+
it 'works' do
|
17
|
+
expect(pipeline).to \
|
18
|
+
receive(:process).and_return([200, {}, ['Hello, world!']])
|
19
|
+
expect(storage).to \
|
20
|
+
receive(:write).with('index.html', ['Hello, world!'])
|
21
|
+
|
22
|
+
subject.process(['index.html'])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|