aleksi-hassle 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009, Pedro Belo, Nick Quaranto
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,117 @@
1
+ h1. Hassle
2
+
3
+ Making "SASS":http://sass-lang.com/ less of a hassle on read only filesystems. (like "Heroku":http://heroku.com)
4
+
5
+ h2. WARNING
6
+
7
+ This plugin doesn't supports Rails 3 yet.
8
+
9
+ h2. Install
10
+
11
+ Get it from "Gemcutter.":http://gemcutter.org
12
+
13
+ <pre>
14
+ gem install hassle -s http://gemcutter.org
15
+ </pre>
16
+
17
+ h2. Usage
18
+
19
+ By default, SASS compiles CSS into the @public/@ directory. On platforms like Heroku, "this won't work.":http://docs.heroku.com/constraints#read-only-filesystem Instead, Hassle compiles the SASS for you into @tmp/@ and serves it up via a @Rack::Static@ middleware.
20
+
21
+ Hassle assumes a few basic things about your setup: There's going to be a @tmp/@ directory where it can write to, and @public/@ is where you store your css. A simple example:
22
+
23
+ <pre>
24
+ $ tree
25
+ .
26
+ |-- config.ru
27
+ |-- public
28
+ | `-- stylesheets
29
+ | `-- sass
30
+ | `-- application.sass
31
+ `-- tmp
32
+ `-- hassle
33
+ `-- stylesheets
34
+ `-- application.css
35
+ </pre>
36
+
37
+ With a basic SASS file in @public/stylesheets/sass/application.sass@, you can include it in your views with:
38
+
39
+ <pre>
40
+ <link href="/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
41
+ </pre>
42
+
43
+ Hassle will look at the default sass directory (@public/stylesheets/sass@) and other input directories given in @Sass::Plugin.options[:template_location]@. CSS files are then compiled into @tmp/@ one directory higher than where you specified. Here's a small example of customization:
44
+
45
+ <pre>
46
+ Sass::Plugin.options[:template_location] = "./public/css/templates"
47
+ </pre>
48
+
49
+ And after Hassle runs...
50
+
51
+ <pre>
52
+ $ tree
53
+ .
54
+ |-- config.ru
55
+ |-- public
56
+ | `-- css
57
+ | `-- templates
58
+ | `-- screen.sass
59
+ `-- tmp
60
+ `-- hassle
61
+ `-- css
62
+ `-- screen.css
63
+ </pre>
64
+
65
+ Include this in your views with:
66
+
67
+ <pre>
68
+ <link href="/css/screen.css" media="screen" rel="stylesheet" type="text/css" />
69
+ </pre>
70
+
71
+ h2. Integration
72
+
73
+ Here's how to integrate it with your favorite web framework:
74
+
75
+ h3. Rails
76
+
77
+ For Rails: @script/plugin install git://github.com/pedro/hassle@. Done. Once you're in production mode, Hassle will kick in and prepare your SASS for all to enjoy.
78
+
79
+ h3. Sinatra
80
+
81
+ Here's a sample config.ru that's "up and running.":http://hassle-sinatra.heroku.com
82
+
83
+ <pre>
84
+ require 'sinatra'
85
+ require 'hassle'
86
+ require 'haml'
87
+
88
+ get '/' do
89
+ haml <<EOF
90
+ %html
91
+ %head
92
+ %link{:rel => 'stylesheet', :href => "stylesheets/application.css"}
93
+ %body
94
+ %h1 Hassle!
95
+ EOF
96
+ end
97
+
98
+ use Hassle
99
+ run Sinatra::Application
100
+ </pre>
101
+
102
+ And its wonderful SASS file:
103
+
104
+ <pre>
105
+ $ cat public/stylesheets/sass/application.sass
106
+ h1
107
+ font-size: 11em
108
+ color: purple
109
+ </pre>
110
+
111
+ h2. Bugs
112
+
113
+ Found some problems? Post 'em in "Issues":http://github.com/pedro/hassle/issues.
114
+
115
+ h2. License
116
+
117
+ Hassle uses the MIT license. Please check the LICENSE file for more details.
data/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ if RAILS_ENV == 'production'
2
+ ActionController::Dispatcher.middleware.use Hassle
3
+ end
@@ -0,0 +1,68 @@
1
+ require 'rack'
2
+ require 'sass'
3
+ require 'sass/plugin'
4
+
5
+ class Hassle
6
+ def initialize(app)
7
+ compiler = Hassle::Compiler.new
8
+ compiler.compile
9
+ @static = Rack::Static.new(app,
10
+ :urls => compiler.stylesheets,
11
+ :root => compiler.compile_location)
12
+ end
13
+
14
+ def call(env)
15
+ @static.call(env)
16
+ end
17
+ end
18
+
19
+ class Hassle::Compiler
20
+ def options
21
+ Sass::Plugin.options
22
+ end
23
+
24
+ def css_location(path)
25
+ expanded = File.expand_path(path)
26
+ public_dir = File.join(File.expand_path(Dir.pwd), "public")
27
+
28
+ File.expand_path(compile_location(expanded.gsub(public_dir, ''), '..'))
29
+ end
30
+
31
+ def compile_location(*subdirs)
32
+ File.join(Dir.pwd, "tmp", "hassle", subdirs)
33
+ end
34
+
35
+ def normalize
36
+ template_location = options[:template_location]
37
+
38
+ if template_location.is_a?(Hash) || template_location.is_a?(Array)
39
+ options[:template_location] = template_location.to_a.map do |input, output|
40
+ [input, css_location(input)]
41
+ end
42
+ else
43
+ default_location = File.join(options[:css_location], "sass")
44
+ options[:template_location] = {default_location => css_location(default_location)}
45
+ end
46
+ end
47
+
48
+ def prepare
49
+ options.merge!(:cache => false,
50
+ :never_update => false)
51
+
52
+ options[:template_location].to_a.each do |location|
53
+ FileUtils.mkdir_p(location.last)
54
+ end
55
+ end
56
+
57
+ def stylesheets
58
+ options[:template_location].to_a.map do |location|
59
+ Dir[File.join(location.last, "**", "*.css")].map { |css| css.gsub(compile_location, "/") }
60
+ end.flatten.sort
61
+ end
62
+
63
+ def compile
64
+ normalize
65
+ prepare
66
+ Sass::Plugin.update_stylesheets
67
+ end
68
+ end
@@ -0,0 +1,60 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'rack/test'
4
+
5
+ require File.dirname(__FILE__) + '/../lib/hassle'
6
+
7
+ SASS_OPTIONS = Sass::Plugin.options.dup
8
+
9
+ SASS_DATA = %[
10
+ $blue: #3bbfce
11
+ .col
12
+ color: $blue
13
+ ]
14
+
15
+ SCSS_DATA = %[
16
+ $blue: #3bbfce;
17
+ .col {
18
+ color: $blue;
19
+ }
20
+ ]
21
+
22
+ def write_data(location, css_file, format)
23
+ FileUtils.mkdir_p(location)
24
+ sass_path = File.join(location, "#{css_file}.#{format}")
25
+ File.open(sass_path, "w") do |f|
26
+ f.write(format == :sass ? SASS_DATA : SCSS_DATA)
27
+ end
28
+
29
+ File.join(@hassle.css_location(location), "#{css_file}.css") if @hassle
30
+ end
31
+
32
+ def write_sass(location, css_file = "screen")
33
+ write_data(location, css_file, :sass)
34
+ end
35
+
36
+ def write_scss(location, css_file = "screen")
37
+ write_data(location, css_file, :scss)
38
+ end
39
+
40
+ def be_compiled
41
+ simple_matcher("exist") { |given| File.exists?(given) }
42
+ simple_matcher("contain compiled sass") { |given| File.read(given) == ".col {\n color: #3bbfce; }\n" }
43
+ end
44
+
45
+ def have_tmp_dir_removed(*stylesheets)
46
+ simple_matcher("remove tmp dir") do |given|
47
+ given == stylesheets.map { |css| css.gsub(File.join(Dir.pwd, "tmp", "hassle"), "") }
48
+ end
49
+ end
50
+
51
+ def have_served_sass
52
+ simple_matcher("return success") { |given| given.status == 200 }
53
+ simple_matcher("compiled sass") { |given| given.body.should == ".col {\n color: #3bbfce; }\n" }
54
+ end
55
+
56
+ def reset
57
+ Sass::Plugin.options.clear
58
+ Sass::Plugin.options = SASS_OPTIONS
59
+ FileUtils.rm_rf([File.join(Dir.pwd, "public"), File.join(Dir.pwd, "tmp")])
60
+ end
@@ -0,0 +1,104 @@
1
+ require File.join(File.dirname(__FILE__), "base")
2
+
3
+ describe Hassle::Compiler do
4
+ before do
5
+ reset
6
+ @hassle = Hassle::Compiler.new
7
+ end
8
+
9
+ it "dumps css into separate folders" do
10
+ @hassle.css_location("./public/stylesheets/sass").should ==
11
+ File.join(Dir.pwd, "tmp", "hassle", "stylesheets")
12
+
13
+ @hassle.css_location("./public/css/compiled").should ==
14
+ File.join(Dir.pwd, "tmp", "hassle", "css")
15
+
16
+ @hassle.css_location("./public/styles/posts/sass").should ==
17
+ File.join(Dir.pwd, "tmp", "hassle", "styles", "posts")
18
+ end
19
+
20
+ describe "compiling sass" do
21
+ before do
22
+ @default_location = Sass::Plugin.options[:css_location]
23
+ end
24
+
25
+ it "moves css into tmp directory with default settings" do
26
+ sass = write_sass(File.join(@default_location, "sass"))
27
+
28
+ @hassle.compile
29
+
30
+ sass.should be_compiled
31
+ @hassle.stylesheets.should have_tmp_dir_removed(sass)
32
+ end
33
+
34
+ it "should not create sass cache" do
35
+ write_sass(File.join(@default_location, "sass"))
36
+ Sass::Plugin.options[:cache] = true
37
+
38
+ @hassle.compile
39
+
40
+ File.exists?(".sass-cache").should be_false
41
+ end
42
+
43
+ it "should compile sass even if disabled with never_update" do
44
+ sass = write_sass(File.join(@default_location, "sass"))
45
+ Sass::Plugin.options[:never_update] = true
46
+
47
+ @hassle.compile
48
+
49
+ sass.should be_compiled
50
+ end
51
+
52
+ it "should compile sass if template location is a hash" do
53
+ new_location = "public/css/sass"
54
+ Sass::Plugin.options[:template_location] = {new_location => "public/css"}
55
+ sass = write_sass(new_location)
56
+
57
+ @hassle.compile
58
+
59
+ sass.should be_compiled
60
+ end
61
+
62
+ it "should compile sass if template location is a hash with multiple locations" do
63
+ location_one = "public/css/sass"
64
+ location_two = "public/stylesheets/sass"
65
+ Sass::Plugin.options[:template_location] = {location_one => "public/css", location_two => "public/css"}
66
+ sass_one = write_sass(location_one, "one")
67
+ sass_two = write_sass(location_two, "two")
68
+
69
+ @hassle.compile
70
+
71
+ sass_one.should be_compiled
72
+ sass_two.should be_compiled
73
+ @hassle.stylesheets.should have_tmp_dir_removed(sass_one, sass_two)
74
+ end
75
+
76
+ it "should compile sass if template location is an array with multiple locations" do
77
+ location_one = "public/css/sass"
78
+ location_two = "public/stylesheets/sass"
79
+ Sass::Plugin.options[:template_location] = [[location_one, "public/css"], [location_two, "public/css"]]
80
+ sass_one = write_sass(location_one, "one")
81
+ sass_two = write_sass(location_two, "two")
82
+
83
+ @hassle.compile
84
+
85
+ sass_one.should be_compiled
86
+ sass_two.should be_compiled
87
+ @hassle.stylesheets.should have_tmp_dir_removed(sass_one, sass_two)
88
+ end
89
+
90
+ it "should not overwrite similarly name files in different directories" do
91
+ location_one = "public/css/sass"
92
+ location_two = "public/stylesheets/sass"
93
+ Sass::Plugin.options[:template_location] = {location_one => "public/css", location_two => "public/css"}
94
+ sass_one = write_sass(location_one, "screen")
95
+ sass_two = write_sass(location_two, "screen")
96
+
97
+ @hassle.compile
98
+
99
+ sass_one.should be_compiled
100
+ sass_two.should be_compiled
101
+ @hassle.stylesheets.should have_tmp_dir_removed(sass_one, sass_two)
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,65 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+
3
+ describe Hassle do
4
+ include Rack::Test::Methods
5
+
6
+ def app
7
+ Rack::Builder.new do
8
+ use Hassle
9
+ run Proc.new {|env| [200, {"Content-Type" => "text/html"}, "hello!"]}
10
+ end
11
+ end
12
+
13
+ before do
14
+ reset
15
+ end
16
+
17
+ it "sends through basic responses" do
18
+ get '/'
19
+ last_response.status.should == 200
20
+ last_response.body.should =~ /hello!/
21
+ end
22
+
23
+ describe "a basic setup" do
24
+ before do
25
+ write_sass("./public/stylesheets/sass")
26
+ end
27
+
28
+ it "serves up some sass" do
29
+ get '/stylesheets/screen.css'
30
+ last_response.should have_served_sass
31
+ end
32
+ end
33
+
34
+ describe "a basic setup with SCSS" do
35
+ before do
36
+ write_scss("./public/stylesheets/sass")
37
+ end
38
+
39
+ it "serves up some sass" do
40
+ get '/stylesheets/screen.css'
41
+ last_response.should have_served_sass
42
+ end
43
+ end
44
+
45
+ describe "a slightly more complex setup" do
46
+ before do
47
+ @location_one = "./public/css/sass"
48
+ @location_two = "./public/stylesheets/sass"
49
+ Sass::Plugin.options[:template_location] = { @location_one => "public/css",
50
+ @location_two => "public/css"}
51
+ write_sass(@location_one, "style")
52
+ write_sass(@location_two, "application")
53
+ end
54
+
55
+ it "serves up some sass from the normal location" do
56
+ get '/stylesheets/application.css'
57
+ last_response.should have_served_sass
58
+ end
59
+
60
+ it "serves up some sass from a different location" do
61
+ get '/css/style.css'
62
+ last_response.should have_served_sass
63
+ end
64
+ end
65
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aleksi-hassle
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Pedro Belo
14
+ - Nick Quaranto
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-06-13 00:00:00 +04:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: rack
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: haml
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: rspec
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ type: :development
63
+ version_requirements: *id003
64
+ - !ruby/object:Gem::Dependency
65
+ name: cucumber
66
+ prerelease: false
67
+ requirement: &id004 !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ type: :development
77
+ version_requirements: *id004
78
+ - !ruby/object:Gem::Dependency
79
+ name: rack-test
80
+ prerelease: false
81
+ requirement: &id005 !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ type: :development
91
+ version_requirements: *id005
92
+ description: Makes SASS less of a hassle on read-only filesystems by compiling and serving it up for you.
93
+ email:
94
+ executables: []
95
+
96
+ extensions: []
97
+
98
+ extra_rdoc_files:
99
+ - LICENSE
100
+ - README.textile
101
+ files:
102
+ - LICENSE
103
+ - README.textile
104
+ - init.rb
105
+ - lib/hassle.rb
106
+ - spec/base.rb
107
+ - spec/hassle_compiler_spec.rb
108
+ - spec/hassle_spec.rb
109
+ has_rdoc: true
110
+ homepage: http://github.com/AlekSi/hassle
111
+ licenses: []
112
+
113
+ post_install_message:
114
+ rdoc_options:
115
+ - --charset=UTF-8
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ hash: 3
124
+ segments:
125
+ - 0
126
+ version: "0"
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ hash: 17
133
+ segments:
134
+ - 1
135
+ - 3
136
+ - 5
137
+ version: 1.3.5
138
+ requirements: []
139
+
140
+ rubyforge_project:
141
+ rubygems_version: 1.3.7
142
+ signing_key:
143
+ specification_version: 3
144
+ summary: Make SASS less of a hassle. Supports Sass 3 / SCSS.
145
+ test_files:
146
+ - spec/base.rb
147
+ - spec/hassle_compiler_spec.rb
148
+ - spec/hassle_spec.rb