sprockets-sass 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Peter Browne
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,102 @@
1
+ sprockets-sass
2
+ ==============
3
+
4
+ **Better Sass integration with [Sprockets 2.0](http://github.com/sstephenson/sprockets)**
5
+
6
+ When using Sprockets 2.0 with Sass you will eventually run into a pretty big issue. `//= require` directives will not allow Sass mixins, variables, etc. to be shared between files. So you'll try to use `@import`, and that'll also blow up in your face. `sprockets-sass` fixes all of this by creating a Sass::Importer that is Sprockets aware.
7
+
8
+ _Note: This works in Rails 3.1, thanks to the [sass-rails gem](http://github.com/rails/sass-rails). But if you want to use Sprockets and Sass anywhere else, like Sinatra, use `sprockets-sass`._
9
+
10
+ ### Features
11
+
12
+ * Imports Sass _partials_ (filenames prepended with "_").
13
+ * Import paths work exactly like `require` directives*.
14
+ * Imports either Sass syntax, or just regular CSS files.
15
+ * Imported files are preprocessed by Sprockets, so `.css.scss.erb` files can be imported.
16
+ Directives from within imported files also work as expected.
17
+ * Standard Sass load paths are not touched, so Compass extensions will work as expected.
18
+
19
+ _* Glob support coming in 0.2.0_
20
+
21
+ ### TODO
22
+
23
+ * Glob support (as mentioned above)
24
+ * Asset path helpers
25
+
26
+
27
+ Installation
28
+ ------------
29
+
30
+ ``` bash
31
+ $ gem install sprockets-sass
32
+ ```
33
+
34
+
35
+ Usage
36
+ -----
37
+
38
+ In your Rack application, setup Sprockets as you normally would, and require "sprockets-sass":
39
+
40
+ ``` ruby
41
+ require "sprockets"
42
+ require "sprockets-sass"
43
+ require "sass"
44
+
45
+ map "/assets" do
46
+ environment = Sprockets::Environment.new
47
+ environment.append_path "assets/stylesheets"
48
+ run environment
49
+ end
50
+
51
+ map "/" do
52
+ run YourRackApp
53
+ end
54
+ ```
55
+
56
+ Now `@import` works essentially just like a `require` directive, but with one essential bonus:
57
+ Sass mixins, variables, etc. work as expected.
58
+
59
+ Given the following Sass _partials_:
60
+
61
+ ``` scss
62
+ // assets/stylesheets/_mixins.scss
63
+ @mixin border-radius($radius) {
64
+ -webkit-border-radius: $radius;
65
+ -moz-border-radius: $radius;
66
+ border-radius: $radius;
67
+ }
68
+ ```
69
+
70
+ ``` scss
71
+ // assets/stylesheets/_settings.scss
72
+ $color: red;
73
+ ```
74
+
75
+ In another file - you can now do this - from within a Sprockets asset:
76
+
77
+ ``` scss
78
+ // assets/stylesheets/application.css.scss
79
+ @import "mixins";
80
+ @import "settings";
81
+
82
+ button {
83
+ @include border-radius(5px);
84
+ color: $color;
85
+ }
86
+ ```
87
+
88
+ And `GET /assets/application.css` would return something like:
89
+
90
+ ``` css
91
+ button {
92
+ -webkit-border-radius: 5px;
93
+ -moz-border-radius: 5px;
94
+ border-radius: 5px;
95
+ color: red; }
96
+ ```
97
+
98
+
99
+ Copyright
100
+ ---------
101
+
102
+ Copyright (c) 2011 [Peter Browne](http://petebrowne.com). See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require "rspec/core/rake_task"
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
@@ -0,0 +1 @@
1
+ require "sprockets/sass"
@@ -0,0 +1,13 @@
1
+ require "sprockets/sass/version"
2
+ require "sprockets/sass/sass_template"
3
+ require "sprockets/sass/scss_template"
4
+ require "sprockets/engines"
5
+
6
+ module Sprockets
7
+ module Sass
8
+ autoload :Importer, "sprockets/sass/importer"
9
+
10
+ ::Sprockets.register_engine ".sass", SassTemplate
11
+ ::Sprockets.register_engine ".scss", ScssTemplate
12
+ end
13
+ end
@@ -0,0 +1,91 @@
1
+ require "sass/importers/base"
2
+ require "pathname"
3
+
4
+ module Sprockets
5
+ module Sass
6
+ class Importer < ::Sass::Importers::Base
7
+ # Reference to the Sprockets context
8
+ attr_reader :context
9
+
10
+ #
11
+ def initialize(context)
12
+ @context = context
13
+ end
14
+
15
+ # @see Sass::Importers::Base#find_relative
16
+ def find_relative(path, base, options)
17
+ engine_from_path(path, options)
18
+ end
19
+
20
+ # @see Sass::Importers::Base#find
21
+ def find(path, options)
22
+ engine_from_path(path, options)
23
+ end
24
+
25
+ # @see Sass::Importers::Base#mtime
26
+ def mtime(path, options)
27
+ if pathname = resolve(path)
28
+ pathname.mtime
29
+ end
30
+ rescue Errno::ENOENT
31
+ nil
32
+ end
33
+
34
+ # @see Sass::Importers::Base#key
35
+ def key(path, options)
36
+ path = Pathname.new(path)
37
+ ["#{self.class.name}:#{path.dirname.expand_path}", path.basename]
38
+ end
39
+
40
+ # @see Sass::Importers::Base#to_s
41
+ def to_s
42
+ "#{self.class.name}:#{context.pathname}"
43
+ end
44
+
45
+ protected
46
+
47
+ # Create a Sass::Engine from the given path.
48
+ # This is where all the magic happens!
49
+ def engine_from_path(path, options)
50
+ pathname = resolve(path) or return nil
51
+ context.depend_on pathname
52
+ ::Sass::Engine.new evaluate(pathname), options.merge(
53
+ :filename => pathname.to_s,
54
+ :syntax => syntax(pathname),
55
+ :importer => self
56
+ )
57
+ end
58
+
59
+ # Finds an asset from the given path. This is where
60
+ # we make Sprockets behave like Sass, and import partial
61
+ # style paths.
62
+ def resolve(path)
63
+ path = Pathname.new(path) unless path.is_a?(Pathname)
64
+ partial = path.dirname.join("_#{path.basename}")
65
+
66
+ resolve_asset(path) || resolve_asset(partial)
67
+ end
68
+
69
+ # Finds the asset using the context from Sprockets.
70
+ def resolve_asset(path)
71
+ context.resolve(path, :content_type => :self)
72
+ rescue ::Sprockets::FileNotFound, ::Sprockets::ContentTypeMismatch
73
+ nil
74
+ end
75
+
76
+ # Returns the Sass syntax of the given path.
77
+ def syntax(path)
78
+ path.to_s.include?(".sass") ? :sass : :scss
79
+ end
80
+
81
+ # Returns the string to be passed to the Sass engine. We use
82
+ # Sprockets to process the file, but we remove any Sass processors
83
+ # because we need to let the Sass::Engine handle that.
84
+ def evaluate(path)
85
+ processors = context.environment.attributes_for(path).processors.dup
86
+ processors.delete_if { |processor| processor < Tilt::SassTemplate }
87
+ context.evaluate path, :processors => processors
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,43 @@
1
+ require "tilt"
2
+
3
+ module Sprockets
4
+ module Sass
5
+ class SassTemplate < Tilt::SassTemplate
6
+
7
+ # A reference to the current Sprockets context
8
+ attr_reader :context
9
+
10
+ # Define the expected syntax for the template
11
+ def syntax
12
+ :sass
13
+ end
14
+
15
+ def prepare
16
+ @context = nil
17
+ @output = nil
18
+ end
19
+
20
+ def evaluate(context, locals, &block)
21
+ @output ||= begin
22
+ @context = context
23
+ ::Sass::Engine.new(data, sass_options).render
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def sass_options
30
+ options.merge(
31
+ :filename => eval_file,
32
+ :line => line,
33
+ :syntax => syntax,
34
+ :importer => importer
35
+ )
36
+ end
37
+
38
+ def importer
39
+ Importer.new context
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ module Sprockets
2
+ module Sass
3
+ class ScssTemplate < SassTemplate
4
+ # Define the expected syntax for the template
5
+ def syntax
6
+ :scss
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ module Sprockets
2
+ module Sass
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ require "sprockets"
2
+ require "sprockets-sass"
3
+ require "construct"
4
+
5
+ # Requires supporting files with custom matchers and macros, etc,
6
+ # in ./support/ and its subdirectories.
7
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
8
+
9
+ RSpec.configure do |config|
10
+ config.include Construct::Helpers
11
+ end
@@ -0,0 +1,112 @@
1
+ require "spec_helper"
2
+
3
+ describe Sprockets::Sass do
4
+ before :each do
5
+ @root = create_construct
6
+ @assets = @root.directory "assets"
7
+ @env = Sprockets::Environment.new @root.to_s
8
+ @env.append_path @assets.to_s
9
+ end
10
+
11
+ after :each do
12
+ @root.destroy!
13
+ end
14
+
15
+ it "processes scss files normally" do
16
+ @assets.file "main.css.scss", "//= require dep"
17
+ @assets.file "dep.css.scss", "body { color: blue; }"
18
+ asset = @env["main.css.scss"]
19
+ asset.to_s.should == "body {\n color: blue; }\n"
20
+ end
21
+
22
+ it "processes sass files normally" do
23
+ @assets.file "main.css.sass", "//= require dep"
24
+ @assets.file "dep.css.sass", "body\n color: blue"
25
+ asset = @env["main.css.sass"]
26
+ asset.to_s.should == "body {\n color: blue; }\n"
27
+ end
28
+
29
+ it "imports standard files" do
30
+ @assets.file "main.css.scss", %(@import "dep";\nbody { color: $color; })
31
+ @assets.file "dep.css.scss", "$color: blue;"
32
+ asset = @env["main.css.scss"]
33
+ asset.to_s.should == "body {\n color: blue; }\n"
34
+ end
35
+
36
+ it "imports partial style files" do
37
+ @assets.file "main.css.scss", %(@import "dep";\nbody { color: $color; })
38
+ @assets.file "_dep.css.scss", "$color: blue;"
39
+ asset = @env["main.css.scss"]
40
+ asset.to_s.should == "body {\n color: blue; }\n"
41
+ end
42
+
43
+ it "imports other syntax" do
44
+ @assets.file "main.css.scss", %(@import "dep";\nbody { color: $color; })
45
+ @assets.file "dep.css.sass", "$color: blue\nhtml\n height: 100%"
46
+ asset = @env["main.css.scss"]
47
+ asset.to_s.should == "html {\n height: 100%; }\n\nbody {\n color: blue; }\n"
48
+ end
49
+
50
+ it "imports files with directives" do
51
+ @assets.file "main.css.scss", %(@import "dep";)
52
+ @assets.file "dep.css", "/*\n *= require subdep\n */"
53
+ @assets.file "subdep.css.scss", "$color: blue;\nbody { color: $color; }"
54
+ asset = @env["main.css.scss"]
55
+ asset.to_s.should include("body {\n color: blue; }\n")
56
+ end
57
+
58
+ it "imports files with additional processors" do
59
+ @assets.file "main.css.scss", %(@import "dep";\nbody { color: $color; })
60
+ @assets.file "dep.css.scss.erb", "$color: <%= 'blue' %>;"
61
+ asset = @env["main.css.scss"]
62
+ asset.to_s.should == "body {\n color: blue; }\n"
63
+ end
64
+
65
+ it "imports relative files" do
66
+ @assets.file "folder/main.css.scss", %(@import "./dep";\nbody { color: $color; })
67
+ @assets.file "folder/dep.css.scss", "$color: blue;"
68
+ asset = @env["folder/main.css.scss"]
69
+ asset.to_s.should == "body {\n color: blue; }\n"
70
+ end
71
+
72
+ it "imports files relative to root" do
73
+ @assets.file "folder/main.css.scss", %(@import "dep";\nbody { color: $color; })
74
+ @assets.file "dep.css.scss", "$color: blue;"
75
+ asset = @env["folder/main.css.scss"]
76
+ asset.to_s.should == "body {\n color: blue; }\n"
77
+ end
78
+
79
+ it "imports files from the assets load path" do
80
+ vendor = @root.directory "vendor"
81
+ @env.append_path vendor.to_s
82
+
83
+ @assets.file "main.css.scss", %(@import "dep";\nbody { color: $color; })
84
+ vendor.file "dep.css.scss", "$color: blue;"
85
+ asset = @env["main.css.scss"]
86
+ asset.to_s.should == "body {\n color: blue; }\n"
87
+ end
88
+
89
+ it "imports files from the Sass load path" do
90
+ vendor = @root.directory "vendor"
91
+ Sass::Engine::DEFAULT_OPTIONS[:load_paths] << vendor.to_s
92
+
93
+ @assets.file "main.css.scss", %(@import "dep";\nbody { color: $color; })
94
+ vendor.file "dep.scss", "$color: blue;"
95
+ asset = @env["main.css.scss"]
96
+ asset.to_s.should == "body {\n color: blue; }\n"
97
+ end
98
+
99
+ it "adds dependency when imported" do
100
+ @assets.file "main.css.scss", %(@import "dep";\nbody { color: $color; })
101
+ dep = @assets.file "dep.css.scss", "$color: blue;"
102
+
103
+ asset = @env["main.css.scss"]
104
+ asset.should be_fresh
105
+
106
+ mtime = Time.now + 1
107
+ dep.open("w") { |f| f.write "$color: red;" }
108
+ dep.utime mtime, mtime
109
+
110
+ asset.should be_stale
111
+ end
112
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "sprockets/sass/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "sprockets-sass"
7
+ s.version = Sprockets::Sass::VERSION
8
+ s.authors = ["Pete Browne"]
9
+ s.email = ["me@petebrowne.com"]
10
+ s.homepage = "http://github.com/petebrowne/sprockets-sass"
11
+ s.summary = %q{Better Sass integration with Sprockets 2.0}
12
+ s.description = %q{When using Sprockets 2.0 with Sass you will eventually run into a pretty big issue. `//= require` directives will not allow Sass mixins, variables, etc. to be shared between files. So you'll try to use `@import`, and that'll also blow up in your face. `sprockets-sass` fixes all of this by creating a Sass::Importer that is Sprockets aware.}
13
+
14
+ s.rubyforge_project = "sprockets-sass"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency "sprockets", "~> 2.0"
22
+ s.add_development_dependency "rake"
23
+ s.add_development_dependency "rspec", "~> 2.6"
24
+ s.add_development_dependency "test-construct", "~> 1.2"
25
+ s.add_development_dependency "sass", "~> 3.1"
26
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sprockets-sass
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Pete Browne
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-09-21 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ version_requirements: &id001 !ruby/object:Gem::Requirement
22
+ none: false
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ hash: 3
27
+ segments:
28
+ - 2
29
+ - 0
30
+ version: "2.0"
31
+ requirement: *id001
32
+ name: sprockets
33
+ prerelease: false
34
+ type: :runtime
35
+ - !ruby/object:Gem::Dependency
36
+ version_requirements: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ hash: 3
42
+ segments:
43
+ - 0
44
+ version: "0"
45
+ requirement: *id002
46
+ name: rake
47
+ prerelease: false
48
+ type: :development
49
+ - !ruby/object:Gem::Dependency
50
+ version_requirements: &id003 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ hash: 15
56
+ segments:
57
+ - 2
58
+ - 6
59
+ version: "2.6"
60
+ requirement: *id003
61
+ name: rspec
62
+ prerelease: false
63
+ type: :development
64
+ - !ruby/object:Gem::Dependency
65
+ version_requirements: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ hash: 11
71
+ segments:
72
+ - 1
73
+ - 2
74
+ version: "1.2"
75
+ requirement: *id004
76
+ name: test-construct
77
+ prerelease: false
78
+ type: :development
79
+ - !ruby/object:Gem::Dependency
80
+ version_requirements: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ hash: 5
86
+ segments:
87
+ - 3
88
+ - 1
89
+ version: "3.1"
90
+ requirement: *id005
91
+ name: sass
92
+ prerelease: false
93
+ type: :development
94
+ description: When using Sprockets 2.0 with Sass you will eventually run into a pretty big issue. `//= require` directives will not allow Sass mixins, variables, etc. to be shared between files. So you'll try to use `@import`, and that'll also blow up in your face. `sprockets-sass` fixes all of this by creating a Sass::Importer that is Sprockets aware.
95
+ email:
96
+ - me@petebrowne.com
97
+ executables: []
98
+
99
+ extensions: []
100
+
101
+ extra_rdoc_files: []
102
+
103
+ files:
104
+ - .gitignore
105
+ - Gemfile
106
+ - LICENSE
107
+ - README.md
108
+ - Rakefile
109
+ - lib/sprockets-sass.rb
110
+ - lib/sprockets/sass.rb
111
+ - lib/sprockets/sass/importer.rb
112
+ - lib/sprockets/sass/sass_template.rb
113
+ - lib/sprockets/sass/scss_template.rb
114
+ - lib/sprockets/sass/version.rb
115
+ - spec/spec_helper.rb
116
+ - spec/sprockets-sass_spec.rb
117
+ - sprockets-sass.gemspec
118
+ homepage: http://github.com/petebrowne/sprockets-sass
119
+ licenses: []
120
+
121
+ post_install_message:
122
+ rdoc_options: []
123
+
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ hash: 3
132
+ segments:
133
+ - 0
134
+ version: "0"
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ hash: 3
141
+ segments:
142
+ - 0
143
+ version: "0"
144
+ requirements: []
145
+
146
+ rubyforge_project: sprockets-sass
147
+ rubygems_version: 1.8.5
148
+ signing_key:
149
+ specification_version: 3
150
+ summary: Better Sass integration with Sprockets 2.0
151
+ test_files:
152
+ - spec/spec_helper.rb
153
+ - spec/sprockets-sass_spec.rb