rail 0.0.7 → 0.0.8
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 +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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed960041649216cdcaeb74ef9689f4e95036b95b
|
4
|
+
data.tar.gz: 9f8d32c3ff9f03a87521958d217a0d12c9cde586
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1738d5b0b7a8725f7e9187edd6f6cc8c96815197167e9e2bf0d50245a27c8d2420807c01d211d0355bc14c98e67ddfccaf43d0dff2ccd93c20f8737cca10c759
|
7
|
+
data.tar.gz: 04cc3ad49ca4dbd80fd4144de9d6684b48a007c303bd1fc0e01ef3657fddb9d158871919d738ecacbf40b02129613bcdaae3c66f93ebd419252809eb951461cd
|
data/CHANGELOG.md
CHANGED
data/Guardfile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
2
|
+
watch(%r{^lib/(.+)\.rb$}) do |match|
|
3
|
+
file = "spec/lib/#{match[1]}_spec.rb"
|
4
|
+
File.exist?(file) ? file : 'spec'
|
5
|
+
end
|
6
|
+
watch(%r{^spec/.*_spec\.rb$})
|
7
|
+
watch(%r{^spec/spec_helper\.rb$}) { 'spec' }
|
8
|
+
end
|
9
|
+
|
10
|
+
# vim: set ft=ruby
|
data/README.md
CHANGED
@@ -8,7 +8,9 @@ assets, and it includes the following components:
|
|
8
8
|
* [Haml](http://haml.info/) for HTML, and
|
9
9
|
* [Sass](http://sass-lang.com/) for CSS.
|
10
10
|
|
11
|
-
##
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
### Straightforward
|
12
14
|
|
13
15
|
Install the gem:
|
14
16
|
|
@@ -42,18 +44,14 @@ current directory called `my_project` and initializes a basic Rail project
|
|
42
44
|
inside that folder. In this case, `MyProject` is used as the class name of
|
43
45
|
the project. Feel free to replace `my_project` with the name of your project.
|
44
46
|
|
45
|
-
|
47
|
+
### Manual
|
46
48
|
|
47
|
-
|
49
|
+
Create a `Gemfile`:
|
48
50
|
|
49
51
|
```ruby
|
50
52
|
source 'https://rubygems.org'
|
51
53
|
|
52
|
-
gem 'rail'
|
53
|
-
|
54
|
-
# The rest is optional
|
55
|
-
gem 'redcarpet', '~> 3.1.2' # your favorit complement to Haml
|
56
|
-
gem 'thin', '~> 1.6.2' # your favorit Web server
|
54
|
+
gem 'rail'
|
57
55
|
```
|
58
56
|
|
59
57
|
Run [Bundler](http://bundler.io/):
|
@@ -122,15 +120,15 @@ As with Rails, Rail is configured inside `config/application.rb`:
|
|
122
120
|
```ruby
|
123
121
|
module MyProject
|
124
122
|
class Application < Rail::Application
|
125
|
-
#
|
126
|
-
config.gems << '
|
123
|
+
# Gems to look for additional assets
|
124
|
+
config.gems << 'googleplus-reader'
|
127
125
|
|
128
|
-
#
|
126
|
+
# Assets to precompile when running `rake assets`
|
129
127
|
config.precompile << 'application.css'
|
130
128
|
config.precompile << 'application.js'
|
131
129
|
config.precompile << 'index.html'
|
132
130
|
|
133
|
-
# Compress assets
|
131
|
+
# Compress assets when serving and precompiling
|
134
132
|
config.compress = true
|
135
133
|
end
|
136
134
|
end
|
data/Rakefile
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
|
-
require '
|
2
|
+
require 'rspec/core/rake_task'
|
3
3
|
|
4
|
-
|
5
|
-
test.libs.push('lib')
|
6
|
-
test.test_files = FileList[ 'spec/*_spec.rb' ]
|
7
|
-
test.verbose = true
|
8
|
-
end
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
9
5
|
|
10
|
-
task :default => :
|
6
|
+
task :default => :spec
|
7
|
+
task :test => :spec
|
data/bin/rail
CHANGED
data/lib/rail.rb
CHANGED
@@ -1,29 +1,30 @@
|
|
1
|
-
require 'ostruct'
|
2
1
|
require 'forwardable'
|
3
|
-
|
4
2
|
require 'rack'
|
5
|
-
|
6
3
|
require 'coffee-script'
|
7
4
|
require 'haml'
|
8
5
|
require 'sass'
|
9
|
-
|
10
6
|
require 'uglifier'
|
11
7
|
|
8
|
+
require_relative 'support/inflector'
|
9
|
+
require_relative 'support/loader'
|
10
|
+
require_relative 'support/query_string'
|
11
|
+
require_relative 'support/query_struct'
|
12
|
+
|
12
13
|
require_relative 'rail/application'
|
13
14
|
require_relative 'rail/browser'
|
14
15
|
require_relative 'rail/context'
|
15
16
|
require_relative 'rail/pipeline'
|
17
|
+
require_relative 'rail/precompiler'
|
16
18
|
require_relative 'rail/processor'
|
17
19
|
require_relative 'rail/request'
|
18
20
|
require_relative 'rail/server'
|
19
|
-
require_relative 'rail/support'
|
20
21
|
require_relative 'rail/version'
|
21
22
|
|
22
23
|
module Rail
|
23
24
|
NotFoundError = Class.new(StandardError)
|
24
25
|
|
25
26
|
def self.env
|
26
|
-
@env ||=
|
27
|
+
@env ||= Support::QueryString.new(ENV['RAIL_ENV'] || 'development')
|
27
28
|
end
|
28
29
|
|
29
30
|
def self.applications
|
@@ -31,19 +32,4 @@ module Rail
|
|
31
32
|
klass < Application
|
32
33
|
end
|
33
34
|
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def self.build_env
|
38
|
-
string = ENV['RAIL_ENV'] ? ENV['RAIL_ENV'].dup : 'development'
|
39
|
-
|
40
|
-
string.singleton_class.class_eval do
|
41
|
-
define_method(:method_missing) do |name, *arguments, &block|
|
42
|
-
super unless name.to_s =~ /^(?<name>.+)\?$/
|
43
|
-
self == Regexp.last_match(:name)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
string
|
48
|
-
end
|
49
35
|
end
|
data/lib/rail/application.rb
CHANGED
@@ -1,16 +1,11 @@
|
|
1
1
|
module Rail
|
2
2
|
class Application
|
3
|
-
|
4
|
-
|
5
|
-
attr_reader :browser, :pipeline
|
6
|
-
def_delegators :config, :root, :gems, :compress?
|
3
|
+
attr_reader :config, :browser, :pipeline
|
7
4
|
|
8
5
|
def initialize
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
@browser = Browser.new(self)
|
13
|
-
@pipeline = Pipeline.new(self)
|
6
|
+
@config = self.class.config
|
7
|
+
@browser = Browser.new(config)
|
8
|
+
@pipeline = Pipeline.new(config)
|
14
9
|
end
|
15
10
|
|
16
11
|
def call(env)
|
@@ -18,95 +13,28 @@ module Rail
|
|
18
13
|
(browser.accept?(request) ? browser : pipeline).process(request)
|
19
14
|
end
|
20
15
|
|
21
|
-
def
|
22
|
-
|
16
|
+
def precompile
|
17
|
+
Precompiler.new(pipeline).process(config.precompile)
|
23
18
|
end
|
24
19
|
|
25
|
-
def
|
26
|
-
|
20
|
+
def self.inherited(klass)
|
21
|
+
klass.config.root = File.expand_path('../..', caller[0].sub(/:.*/, ''))
|
27
22
|
end
|
28
23
|
|
29
24
|
def self.config
|
30
|
-
@config ||=
|
25
|
+
@config ||= Support::QueryStruct.new(default_options)
|
31
26
|
end
|
32
27
|
|
33
28
|
def self.load_tasks
|
34
|
-
# Rakefile
|
35
|
-
config.root ||= find_root
|
36
|
-
|
37
29
|
Dir[File.join(File.dirname(__FILE__), 'tasks/*.rake')].each do |path|
|
38
30
|
Rake::load_rakefile(path)
|
39
31
|
end
|
40
32
|
end
|
41
33
|
|
42
|
-
def self.precompile
|
43
|
-
if config.precompile.empty?
|
44
|
-
puts 'Nothing to precompile.'
|
45
|
-
return
|
46
|
-
end
|
47
|
-
|
48
|
-
application = self.new
|
49
|
-
|
50
|
-
puts 'Precompiling assets...'
|
51
|
-
puts
|
52
|
-
|
53
|
-
config.precompile.each do |path|
|
54
|
-
file = File.join('public', path)
|
55
|
-
unless File.exist?(File.dirname(file))
|
56
|
-
FileUtils.mkdir_p(File.dirname(file))
|
57
|
-
end
|
58
|
-
|
59
|
-
puts "#{ path } -> #{ file }"
|
60
|
-
|
61
|
-
request = Request.new('REQUEST_METHOD' => 'GET', 'PATH_INFO' => path)
|
62
|
-
_, _, source = application.pipeline.process(request)
|
63
|
-
|
64
|
-
File.open(file, 'w') do |file|
|
65
|
-
source.each { |chunk| file.write(chunk) }
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
puts
|
70
|
-
puts 'Done.'
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.find_root
|
74
|
-
File.expand_path('..', caller[1].sub(/:.*/, ''))
|
75
|
-
end
|
76
|
-
|
77
34
|
private
|
78
35
|
|
79
|
-
def load_helpers
|
80
|
-
Dir[File.join(root, 'app/helpers/*.rb')].map do |file|
|
81
|
-
require file
|
82
|
-
Support.constantize(File.basename(file, '.rb'))
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
36
|
def self.default_options
|
87
|
-
{
|
88
|
-
gems: [],
|
89
|
-
precompile: [],
|
90
|
-
compress: Rail.env.production?
|
91
|
-
}
|
37
|
+
{ gems: [], precompile: [], compress: Rail.env.production? }
|
92
38
|
end
|
93
|
-
|
94
|
-
def self.build_config
|
95
|
-
struct = OpenStruct.new
|
96
|
-
|
97
|
-
struct.singleton_class.class_eval do
|
98
|
-
define_method(:method_missing) do |name, *arguments, &block|
|
99
|
-
!!super(name.to_s.sub(/\?$/, '').to_sym, *arguments, &block)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
default_options.each do |name, value|
|
104
|
-
struct.send("#{ name }=", value)
|
105
|
-
end
|
106
|
-
|
107
|
-
struct
|
108
|
-
end
|
109
|
-
|
110
|
-
private_class_method :default_options, :build_config
|
111
39
|
end
|
112
40
|
end
|
data/lib/rail/browser.rb
CHANGED
@@ -2,23 +2,19 @@ require 'rack'
|
|
2
2
|
|
3
3
|
module Rail
|
4
4
|
class Browser
|
5
|
-
|
5
|
+
attr_reader :root
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def initialize(host)
|
11
|
-
@host = host
|
12
|
-
@directory ||= Rack::Directory.new(File.join(root, 'public'))
|
7
|
+
def initialize(config)
|
8
|
+
@root = File.join(config.root, 'public')
|
9
|
+
@directory = Rack::Directory.new(root)
|
13
10
|
end
|
14
11
|
|
15
12
|
def process(request)
|
16
|
-
call(request.env)
|
13
|
+
@directory.call(request.env)
|
17
14
|
end
|
18
15
|
|
19
16
|
def accept?(request)
|
20
|
-
|
21
|
-
!path.empty? && File.exist?(File.join(root, 'public', path))
|
17
|
+
File.exist?(File.join(root, request.path))
|
22
18
|
end
|
23
19
|
end
|
24
20
|
end
|
data/lib/rail/generator.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
require 'generator'
|
1
|
+
require 'support/generator'
|
2
|
+
require 'support/inflector'
|
2
3
|
|
3
4
|
module Rail
|
4
|
-
class Generator < ::Generator
|
5
|
-
Error = Class.new(StandardError)
|
6
|
-
|
5
|
+
class Generator < Support::Generator
|
7
6
|
FILES = [
|
8
7
|
'app/assets/javascripts/application.js.coffee',
|
9
8
|
'app/assets/stylesheets/application.css.scss',
|
@@ -17,31 +16,25 @@ module Rail
|
|
17
16
|
]
|
18
17
|
|
19
18
|
def initialize(options)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
project_name = (root_dir.split('/').last || '')
|
24
|
-
.gsub(/^[^a-zA-Z]*/, '')
|
25
|
-
.gsub(/[^\w]/, '')
|
26
|
-
.gsub(/^\w|_\w/, &:upcase)
|
27
|
-
.gsub(/_+/, ' ')
|
19
|
+
destination = options.fetch(:destination)
|
20
|
+
source = File.expand_path('../templates', __FILE__)
|
28
21
|
|
22
|
+
directory = destination.split('/').last || ''
|
23
|
+
project_name = Support::Inflector.titelize(directory)
|
29
24
|
class_name = project_name.gsub(' ', '')
|
30
25
|
|
31
26
|
@locals = { class_name: class_name, project_name: project_name }
|
32
27
|
|
33
|
-
raise
|
28
|
+
raise ArgumentError, 'The project name is invalid.' if class_name.empty?
|
34
29
|
|
35
|
-
super(
|
30
|
+
super(destination: destination, source: source)
|
36
31
|
end
|
37
32
|
|
38
33
|
def run
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def report(message)
|
44
|
-
puts "Creating '#{ message }'..."
|
34
|
+
if File.directory?(destination)
|
35
|
+
raise ArgumentError, 'The directory already exists.'
|
36
|
+
end
|
37
|
+
process(FILES, @locals)
|
45
38
|
end
|
46
39
|
end
|
47
40
|
end
|
data/lib/rail/pipeline.rb
CHANGED
@@ -2,14 +2,16 @@ module Rail
|
|
2
2
|
class Pipeline
|
3
3
|
extend Forwardable
|
4
4
|
|
5
|
-
|
5
|
+
attr_reader :config
|
6
|
+
def_delegators :config, :root, :gems, :compress?
|
6
7
|
|
7
|
-
def initialize(
|
8
|
-
@
|
8
|
+
def initialize(config)
|
9
|
+
@config = config
|
10
|
+
@loader = Support::Loader.new(File.join(root, 'app/helpers/*.rb'))
|
9
11
|
end
|
10
12
|
|
11
13
|
def process(request)
|
12
|
-
context = Context.new(locals: { request: request }, mixins:
|
14
|
+
context = Context.new(locals: { request: request }, mixins: loader.find)
|
13
15
|
|
14
16
|
asset = rewrite(request.path)
|
15
17
|
klass = Processor.find(asset) or raise NotFoundError
|
@@ -21,9 +23,9 @@ module Rail
|
|
21
23
|
|
22
24
|
headers = { 'Content-Type' => klass.mime_type }
|
23
25
|
|
24
|
-
[
|
26
|
+
[200, headers, Array(body)]
|
25
27
|
rescue NotFoundError
|
26
|
-
[
|
28
|
+
[404, {}, []]
|
27
29
|
end
|
28
30
|
|
29
31
|
def find(asset)
|
@@ -36,14 +38,12 @@ module Rail
|
|
36
38
|
|
37
39
|
private
|
38
40
|
|
41
|
+
attr_reader :loader
|
42
|
+
|
39
43
|
def rewrite(path)
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
"#{ path }.html"
|
44
|
-
else
|
45
|
-
path
|
46
|
-
end
|
44
|
+
path = path.sub(/^\//, '')
|
45
|
+
path = 'layouts/application.html' if path == 'index.html'
|
46
|
+
path
|
47
47
|
end
|
48
48
|
|
49
49
|
def paths
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Rail
|
2
|
+
class Precompiler
|
3
|
+
class Storage
|
4
|
+
attr_reader :root
|
5
|
+
|
6
|
+
def initialize(root = 'public')
|
7
|
+
@root = root
|
8
|
+
end
|
9
|
+
|
10
|
+
def write(file, stream)
|
11
|
+
file = File.join(root, file)
|
12
|
+
|
13
|
+
unless File.exist?(File.dirname(file))
|
14
|
+
FileUtils.mkdir_p(File.dirname(file))
|
15
|
+
end
|
16
|
+
|
17
|
+
File.open(file, 'w') do |file|
|
18
|
+
stream.each { |chunk| file.write(chunk) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(pipeline, storage = nil)
|
24
|
+
@pipeline = pipeline
|
25
|
+
@storage = storage || Storage.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def process(paths)
|
29
|
+
if paths.empty?
|
30
|
+
report('Nothing to precompile.')
|
31
|
+
return
|
32
|
+
end
|
33
|
+
|
34
|
+
report('Precompiling assets...')
|
35
|
+
|
36
|
+
paths.each_with_index do |path, i|
|
37
|
+
report('%4d. %s' % [i + 1, path])
|
38
|
+
storage.write(path, read(path))
|
39
|
+
end
|
40
|
+
|
41
|
+
report('Done.')
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
attr_reader :pipeline, :storage
|
47
|
+
|
48
|
+
def read(path)
|
49
|
+
request = Request.new('REQUEST_METHOD' => 'GET', 'PATH_INFO' => path)
|
50
|
+
_, _, source = pipeline.process(request)
|
51
|
+
source
|
52
|
+
end
|
53
|
+
|
54
|
+
def report(message)
|
55
|
+
puts message
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|