rail 0.0.5 → 0.0.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 37044477e117facbe9e5e675ee19e1b8088d5aa6
4
- data.tar.gz: 0588d8fd31eab039d6fc11344a4779a6b068f848
3
+ metadata.gz: 43471296d43318f06e1781bfea739eb39bf8da7f
4
+ data.tar.gz: be098116b23160188c2696295bc7758d8876f1d7
5
5
  SHA512:
6
- metadata.gz: 2a4eda036b542c53e9fdb22a25c13d476beb4cb6fdb370404ac3e5796abf9f90bd418fb32a4d3162d31edc27f335be4ab97dc948327d3679cfcdc96042d7422d
7
- data.tar.gz: dde7176c4d1b6c5bae9b79cc3e39dec81188dbdd0ffe49bc0973f312720282357e0318b762c7893ef45b8920ba951fbfc31606487d5da8dd83ff8bcbc4b4ed68
6
+ metadata.gz: 4f0f8b61cfef6396c5a1cc20cf14b04413eff13161ea2bc347b7131cc2ad036432ce5dab6162e93e48cf87b9721af39b7ecee7147810c00b4b2eacdc97bb84c7
7
+ data.tar.gz: 8143e93f3ec6e07273f04d0ac0854977a67a72373f70bdaa4c2659895b6a3cee2bb933b18079dda6c242855a30e570b11ad6b508df896bafcfe82be61883c323
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  *.swp
2
- Gemfile.lock
3
- pkg
2
+ .sass-cache
4
3
  .yardoc
4
+ Gemfile.lock
5
5
  doc
6
+ pkg
data/CHANGELOG.md CHANGED
@@ -1,14 +1,19 @@
1
+ ## Rail (develop)
2
+
3
+ * Dropped the dependency on Sprockets.
4
+ * Implemented the rendering of templates inside layouts.
5
+
1
6
  ## Rail 0.0.5 (June 29, 2014)
2
7
 
3
- * Enforced usage of the pipeline when precompiling assets.
8
+ * Enforced the usage of the pipeline when precompiling assets.
4
9
 
5
10
  ## Rail 0.0.4 (June 26, 2014)
6
11
 
7
- * Proper format of README making YARD happy.
12
+ * Changed the format of README to make YARD happy.
8
13
 
9
14
  ## Rail 0.0.3 (June 24, 2014)
10
15
 
11
- * Proper response headers when pipelining assets.
16
+ * Set proper response headers when pipelining assets.
12
17
 
13
18
  ## Rail 0.0.2 (June 21, 2014)
14
19
 
data/README.md CHANGED
@@ -1,14 +1,12 @@
1
1
  # Rail [![Gem Version](https://badge.fury.io/rb/rail.svg)](http://badge.fury.io/rb/rail) [![Dependency Status](https://gemnasium.com/IvanUkhov/rail.svg)](https://gemnasium.com/IvanUkhov/rail) [![Build Status](https://travis-ci.org/IvanUkhov/rail.svg?branch=master)](https://travis-ci.org/IvanUkhov/rail)
2
2
 
3
3
  A light framework for front-end development inspired by
4
- [Rails](http://rubyonrails.org/). It is solely based on
5
- [Sprockets](https://github.com/sstephenson/sprockets) and includes the
6
- following components out of the box:
4
+ [Rails](http://rubyonrails.org/). The sole purpose of Rail is to compile
5
+ assets, and it includes the following components:
7
6
 
8
7
  * [CoffeeScript](http://coffeescript.org/) for JavaScript,
9
- * [Haml](http://haml.info/) for HTML,
10
- * [Sass](http://sass-lang.com/) for CSS, and
11
- * [Uglifier](https://github.com/lautis/uglifier) for compression.
8
+ * [Haml](http://haml.info/) for HTML, and
9
+ * [Sass](http://sass-lang.com/) for CSS.
12
10
 
13
11
  ## Installation
14
12
 
@@ -17,7 +15,7 @@ First of all, include the gem in your `Gemfile`. Here is an example:
17
15
  ```ruby
18
16
  source 'https://rubygems.org'
19
17
 
20
- gem 'rail', '~> 0.0.5'
18
+ gem 'rail', '~> 0.0.6'
21
19
 
22
20
  # The rest is optional
23
21
  gem 'redcarpet', '~> 3.1.2' # your favorit complement to Haml
@@ -75,8 +73,13 @@ Organize your code according to the following convention:
75
73
  * `app/helpers` for helper modules, and
76
74
  * `public` for other static content.
77
75
 
78
- In addition, `app/views/layouts/application.html.haml` will be used for
79
- rendering the root of your application (both `/` and `/index.html`).
76
+ The templates in `app/views/layouts` have a special purpose. First,
77
+ `application.html.haml` is used for rendering the root of your application
78
+ (both `/` and `/index.html`). Second, any template in `layouts` is used as
79
+ a layout for the templates in the subfolder of `views` that has the same name
80
+ as the layout. For example, `articles/what-is-the-meaning-of-life.html.haml`
81
+ will be rendered in the context of `layouts/articles.html.haml` provided
82
+ that the latter has a placeholder for the former via the `yield` keyword.
80
83
 
81
84
  ### Configuration
82
85
 
@@ -124,7 +127,7 @@ delete the precompiled files when you change your code in `app`.
124
127
  ### Examples
125
128
 
126
129
  Additional usage examples can be found
127
- [here](https://github.com/IvanUkhov/type-works),
130
+ [here](https://github.com/IvanUkhov/opentype-works),
128
131
  [here](https://github.com/IvanUkhov/photography), and
129
132
  [here](https://github.com/IvanUkhov/liu-profile).
130
133
 
@@ -0,0 +1,12 @@
1
+ module Rail
2
+ class Context
3
+ def initialize(options = {})
4
+ (options[:mixins] || []).each { |mixin| extend(mixin) }
5
+ singleton_class.class_eval do
6
+ (options[:locals] || {}).each do |name, value|
7
+ define_method(name) { value }
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
data/lib/rail/pipeline.rb CHANGED
@@ -9,58 +9,45 @@ module Rail
9
9
  end
10
10
 
11
11
  def process(request)
12
- Thread.current[:request] = request
12
+ context = Context.new(locals: { request: request }, mixins: helpers)
13
13
 
14
- path = request.path
14
+ asset = rewrite(request.path)
15
+ klass = Processor.find(asset) or raise NotFoundError
16
+ asset = klass.extensify(asset)
17
+ filename = find(asset) or raise NotFoundError
15
18
 
16
- case path
17
- when '', 'index.html'
18
- path = 'layouts/application'
19
- end
19
+ processor = klass.new(self)
20
+ body = processor.compile(filename, context: context)
20
21
 
21
- path = "#{ path }.html" if File.extname(path).empty?
22
+ headers = { 'Content-Type' => klass.mime_type }
22
23
 
23
- sprockets.call('PATH_INFO' => path)
24
+ [ 200, headers, Array(body) ]
25
+ rescue NotFoundError
26
+ [ 404, {}, [] ]
24
27
  end
25
28
 
26
- private
27
-
28
- def sprockets
29
- @sprockets ||= build_sprockets
30
- end
31
-
32
- def build_sprockets
33
- environment = Sprockets::Environment.new
34
-
35
- paths.each do |directory|
36
- environment.append_path(directory)
29
+ def find(asset)
30
+ paths.each do |path|
31
+ filename = File.join(path, asset)
32
+ return filename if File.exist?(filename)
37
33
  end
34
+ nil
35
+ end
38
36
 
39
- if compress?
40
- environment.js_compressor = :uglify
41
- environment.css_compressor = :scss
42
- end
43
-
44
- # TODO: Find a per-instance way to configure HAML.
45
- Haml::Options.defaults[:ugly] = compress?
46
-
47
- helpers.each do |helper|
48
- environment.context_class.class_eval do
49
- include helper
50
- end
51
- end
37
+ private
52
38
 
53
- environment.context_class.class_eval do
54
- define_method(:request) do
55
- Thread.current[:request]
56
- end
39
+ def rewrite(path)
40
+ if [ '', 'index.html' ].include?(path)
41
+ 'layouts/application.html'
42
+ elsif File.extname(path).empty?
43
+ "#{ path }.html"
44
+ else
45
+ path
57
46
  end
58
-
59
- environment
60
47
  end
61
48
 
62
49
  def paths
63
- (application_paths + gems.map { |name| gem_paths(name) }).flatten
50
+ @paths ||= (application_paths + gems.map { |gem| gem_paths(gem) }).flatten
64
51
  end
65
52
 
66
53
  def application_paths
@@ -0,0 +1,22 @@
1
+ module Rail
2
+ module Processor
3
+ class Base
4
+ extend Forwardable
5
+
6
+ def self.capable?(extension)
7
+ Array(output_extension).include?(extension)
8
+ end
9
+
10
+ def self.extensify(filename)
11
+ "#{ filename }.#{ input_extension }"
12
+ end
13
+
14
+ attr_reader :pipeline
15
+ def_delegator :pipeline, :compress?
16
+
17
+ def initialize(pipeline)
18
+ @pipeline = pipeline
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,68 @@
1
+ module Rail
2
+ module Processor
3
+ class CoffeeScript < Base
4
+ def self.input_extension
5
+ 'coffee'
6
+ end
7
+
8
+ def self.output_extension
9
+ 'js'
10
+ end
11
+
12
+ def self.mime_type
13
+ 'application/javascript'
14
+ end
15
+
16
+ def compile(filename, options = {})
17
+ code = process(filename, options)
18
+ code = Uglifier.new.compile(code) if compress?
19
+ code
20
+ end
21
+
22
+ private
23
+
24
+ def process(filename, options = {})
25
+ output = []
26
+
27
+ code = File.read(filename)
28
+
29
+ extract_requirements(code).each do |name|
30
+ requirement_filename = find_requirement(name, filename)
31
+ raise NotFoundError unless requirement_filename
32
+ output << compile(requirement_filename, options)
33
+ end
34
+
35
+ output << ::CoffeeScript.compile(code, options)
36
+
37
+ output.join
38
+ end
39
+
40
+ def find_requirement(name, referrer)
41
+ assets = [ name, "#{ name }.coffee", "#{ name }.js.coffee" ]
42
+
43
+ if name =~ /^\.\// # relative?
44
+ path = File.dirname(referrer)
45
+ assets.each do |asset|
46
+ filename = File.join(path, asset)
47
+ return filename if File.exist?(filename)
48
+ end
49
+ else
50
+ assets.each do |asset|
51
+ filename = pipeline.find(asset)
52
+ return filename if filename
53
+ end
54
+ end
55
+
56
+ nil
57
+ end
58
+
59
+ def extract_requirements(code)
60
+ match = /\A(?:\s*(?:\#.*\n?)+)+/.match(code) or return []
61
+ match[0].split(/\n/).map(&:strip).reject(&:empty?).map do |line|
62
+ match = /^\s*\#\s*=\s*require\s+(.*)$/.match(line)
63
+ match ? match[1].strip.gsub(/(^['"])|(['"]$)/, '') : nil
64
+ end.compact
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,50 @@
1
+ module Rail
2
+ module Processor
3
+ class Haml < Base
4
+ def self.input_extension
5
+ 'haml'
6
+ end
7
+
8
+ def self.output_extension
9
+ 'html'
10
+ end
11
+
12
+ def self.mime_type
13
+ 'text/html'
14
+ end
15
+
16
+ def compile(filename, options = {}, &block)
17
+ options = {
18
+ filename: filename,
19
+ line: 1,
20
+ ugly: compress?
21
+ }.merge(options)
22
+
23
+ engine = ::Haml::Engine.new(File.read(filename), options)
24
+
25
+ layout_filename = find_layout(filename)
26
+
27
+ if layout_filename
28
+ compile(layout_filename, options) do
29
+ engine.render(options[:context], {}, &block)
30
+ end
31
+ else
32
+ engine.render(options[:context], {}, &block)
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def find_layout(filename)
39
+ asset = "layouts/#{ filename.split('/')[-2] }"
40
+
41
+ [ "#{ asset }.haml", "#{ asset }.html.haml" ].each do |asset|
42
+ filename = pipeline.find(asset)
43
+ return filename if filename
44
+ end
45
+
46
+ nil
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,29 @@
1
+ module Rail
2
+ module Processor
3
+ class Sass < Base
4
+ def self.input_extension
5
+ 'scss'
6
+ end
7
+
8
+ def self.output_extension
9
+ 'css'
10
+ end
11
+
12
+ def self.mime_type
13
+ 'text/css'
14
+ end
15
+
16
+ def compile(filename, options = {})
17
+ options = {
18
+ filename: filename,
19
+ line: 1,
20
+ syntax: :scss,
21
+ style: compress? ? :compressed : :nested
22
+ }.merge(options)
23
+
24
+ engine = ::Sass::Engine.new(File.read(filename), options)
25
+ engine.render
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ require_relative 'processor/base'
2
+ require_relative 'processor/coffee_script'
3
+ require_relative 'processor/haml'
4
+ require_relative 'processor/sass'
5
+
6
+ module Rail
7
+ module Processor
8
+ def self.processors
9
+ @processors ||= Processor.constants.map do |name|
10
+ object = Processor.const_get(name)
11
+ object.is_a?(Class) && object < Base ? object : nil
12
+ end.compact
13
+ end
14
+
15
+ def self.find(filename)
16
+ extension = File.extname(filename).slice(1..-1)
17
+ processors.find { |processor| processor.capable?(extension) }
18
+ end
19
+ end
20
+ end
data/lib/rail/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rail
2
- VERSION = '0.0.5'
2
+ VERSION = '0.0.6'
3
3
  end
data/lib/rail.rb CHANGED
@@ -2,21 +2,26 @@ require 'ostruct'
2
2
  require 'forwardable'
3
3
 
4
4
  require 'rack'
5
+
6
+ require 'coffee-script'
5
7
  require 'haml'
8
+ require 'sass'
9
+
6
10
  require 'uglifier'
7
- require 'sprockets'
8
11
 
9
12
  require_relative 'rail/application'
10
13
  require_relative 'rail/browser'
14
+ require_relative 'rail/context'
11
15
  require_relative 'rail/pipeline'
16
+ require_relative 'rail/processor'
12
17
  require_relative 'rail/request'
13
18
  require_relative 'rail/server'
14
19
  require_relative 'rail/support'
15
20
  require_relative 'rail/version'
16
21
 
17
- Sprockets.register_engine('.haml', Tilt::HamlTemplate)
18
-
19
22
  module Rail
23
+ NotFoundError = Class.new(StandardError)
24
+
20
25
  def self.env
21
26
  @env ||= build_env
22
27
  end
data/rail.gemspec CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_dependency 'rake'
26
26
 
27
- spec.add_dependency 'sprockets', '~> 2.12'
27
+ spec.add_dependency 'rack', '~> 1.5'
28
28
 
29
29
  spec.add_dependency 'coffee-script', '~> 2.2'
30
30
  spec.add_dependency 'haml', '~> 4.0'
data/spec/coffee_spec.rb CHANGED
@@ -10,6 +10,17 @@ describe Rail::Application do
10
10
  end
11
11
  body = controller.process('/application.js')
12
12
  assert_equal body.strip, <<-BODY.strip
13
+ (function() {
14
+ window.Parser = (function() {
15
+ function Parser(format) {
16
+ this.format = format;
17
+ }
18
+
19
+ return Parser;
20
+
21
+ })();
22
+
23
+ }).call(this);
13
24
  (function() {
14
25
  window.Font = (function() {
15
26
  function Font(name) {
@@ -36,7 +47,7 @@ describe Rail::Application do
36
47
  end
37
48
  body = controller.process('/application.js')
38
49
  assert_equal body.strip, <<-BODY.strip
39
- (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);
50
+ (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);
40
51
  BODY
41
52
  end
42
53
  end
data/spec/haml_spec.rb CHANGED
@@ -36,6 +36,24 @@ describe Rail::Application do
36
36
  <body>
37
37
  <h1>Hello</h1>
38
38
  </body>
39
+ </html>
40
+ BODY
41
+ end
42
+
43
+ it 'handles layouts' do
44
+ controller = Controller.new do
45
+ config.compress = false
46
+ end
47
+ body = controller.process('/articles/about')
48
+ assert_equal body.strip, <<-BODY.strip
49
+ <!DOCTYPE html>
50
+ <html>
51
+ <head>
52
+ <title>Hello</title>
53
+ </head>
54
+ <body>
55
+ <h1>About</h1>
56
+ </body>
39
57
  </html>
40
58
  BODY
41
59
  end
@@ -1,2 +1,4 @@
1
+ #= require "./parser.js"
2
+
1
3
  class window.Font
2
4
  constructor: (@name) ->
@@ -0,0 +1,2 @@
1
+ class window.Parser
2
+ constructor: (@format) ->
@@ -0,0 +1,5 @@
1
+ module ApplicationHelper
2
+ def title
3
+ 'Hello'
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ %h1 About
@@ -1,6 +1,6 @@
1
1
  !!! 5
2
2
  %html
3
3
  %head
4
- %title Hello
4
+ %title= title
5
5
  %body
6
- %h1 Hello
6
+ %h1= request.host || title
@@ -0,0 +1,6 @@
1
+ !!! 5
2
+ %html
3
+ %head
4
+ %title= title
5
+ %body
6
+ = yield
@@ -8,6 +8,6 @@ class Controller
8
8
 
9
9
  def process(path)
10
10
  _, _, body = @application.call('PATH_INFO' => path)
11
- body.to_s
11
+ body.join.to_s
12
12
  end
13
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rail
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Ukhov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-29 00:00:00.000000000 Z
11
+ date: 2014-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -25,19 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: sprockets
28
+ name: rack
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.12'
33
+ version: '1.5'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.12'
40
+ version: '1.5'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: coffee-script
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -127,7 +127,13 @@ files:
127
127
  - lib/rail.rb
128
128
  - lib/rail/application.rb
129
129
  - lib/rail/browser.rb
130
+ - lib/rail/context.rb
130
131
  - lib/rail/pipeline.rb
132
+ - lib/rail/processor.rb
133
+ - lib/rail/processor/base.rb
134
+ - lib/rail/processor/coffee_script.rb
135
+ - lib/rail/processor/haml.rb
136
+ - lib/rail/processor/sass.rb
131
137
  - lib/rail/request.rb
132
138
  - lib/rail/server.rb
133
139
  - lib/rail/support.rb
@@ -139,9 +145,13 @@ files:
139
145
  - spec/haml_spec.rb
140
146
  - spec/project/app/assets/javascripts/application.js.coffee
141
147
  - spec/project/app/assets/javascripts/font.coffee
148
+ - spec/project/app/assets/javascripts/parser.js.coffee
142
149
  - spec/project/app/assets/stylesheets/_reset.scss
143
150
  - spec/project/app/assets/stylesheets/application.css.scss
151
+ - spec/project/app/helpers/application_helper.rb
152
+ - spec/project/app/views/articles/about.html.haml
144
153
  - spec/project/app/views/layouts/application.html.haml
154
+ - spec/project/app/views/layouts/articles.html.haml
145
155
  - spec/project/config/application.rb
146
156
  - spec/project/controller.rb
147
157
  - spec/sass_spec.rb
@@ -174,9 +184,13 @@ test_files:
174
184
  - spec/haml_spec.rb
175
185
  - spec/project/app/assets/javascripts/application.js.coffee
176
186
  - spec/project/app/assets/javascripts/font.coffee
187
+ - spec/project/app/assets/javascripts/parser.js.coffee
177
188
  - spec/project/app/assets/stylesheets/_reset.scss
178
189
  - spec/project/app/assets/stylesheets/application.css.scss
190
+ - spec/project/app/helpers/application_helper.rb
191
+ - spec/project/app/views/articles/about.html.haml
179
192
  - spec/project/app/views/layouts/application.html.haml
193
+ - spec/project/app/views/layouts/articles.html.haml
180
194
  - spec/project/config/application.rb
181
195
  - spec/project/controller.rb
182
196
  - spec/sass_spec.rb