glebtv-compass-rails 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +22 -0
  4. data/CHANGELOG.md +71 -0
  5. data/Gemfile +17 -0
  6. data/LICENSE +22 -0
  7. data/README.md +97 -0
  8. data/Rakefile +25 -0
  9. data/gemfiles/rails31.gemfile +18 -0
  10. data/gemfiles/rails32.gemfile +18 -0
  11. data/gemfiles/rails40.gemfile +18 -0
  12. data/gemfiles/rails42.gemfile +18 -0
  13. data/glebtv-compass-rails.gemspec +21 -0
  14. data/lib/compass-rails.rb +107 -0
  15. data/lib/compass-rails/configuration.rb +77 -0
  16. data/lib/compass-rails/patches.rb +33 -0
  17. data/lib/compass-rails/patches/compass.rb +12 -0
  18. data/lib/compass-rails/patches/importer.rb +24 -0
  19. data/lib/compass-rails/patches/sass_importer.rb +90 -0
  20. data/lib/compass-rails/patches/sprite_importer.rb +30 -0
  21. data/lib/compass-rails/patches/static_compiler.rb +12 -0
  22. data/lib/compass-rails/railtie.rb +51 -0
  23. data/lib/compass-rails/version.rb +5 -0
  24. data/lib/glebtv-compass-rails.rb +1 -0
  25. data/test/compass_rails_spec.rb +39 -0
  26. data/test/fixtures/.gitkeep +0 -0
  27. data/test/fixtures/assets/images/letters/a.png +0 -0
  28. data/test/fixtures/assets/images/letters/b.png +0 -0
  29. data/test/fixtures/assets/images/numbers/sprite-1.png +0 -0
  30. data/test/fixtures/assets/images/numbers/sprite-2.png +0 -0
  31. data/test/fixtures/assets/stylesheets/application.css.scss +23 -0
  32. data/test/fixtures/assets/stylesheets/partials/_partial_1.scss +3 -0
  33. data/test/fixtures/assets/stylesheets/partials/_partial_2.scss +3 -0
  34. data/test/helpers/command_helper.rb +105 -0
  35. data/test/helpers/debug_helper.rb +12 -0
  36. data/test/helpers/file_helper.rb +38 -0
  37. data/test/helpers/rails_helper.rb +53 -0
  38. data/test/helpers/rails_project.rb +76 -0
  39. data/test/test_helper.rb +20 -0
  40. metadata +128 -0
@@ -0,0 +1,77 @@
1
+ module CompassRails
2
+ module Configuration
3
+ def default_images_dir
4
+ File.join("app", "assets", "images")
5
+ end
6
+
7
+ def default_fonts_dir
8
+ File.join("app", "assets", "fonts")
9
+ end
10
+
11
+ def default_javascripts_dir
12
+ File.join("app", "assets", "javascripts")
13
+ end
14
+
15
+ def default_css_dir
16
+ File.join('public', CompassRails.prefix)
17
+ end
18
+
19
+ def default_http_path
20
+ File.join(CompassRails.prefix)
21
+ end
22
+
23
+ def default_http_images_path
24
+ "#{top_level.http_path}"
25
+ end
26
+
27
+ def default_http_javascripts_path
28
+ "#{top_level.http_path}"
29
+ end
30
+
31
+ def default_http_fonts_path
32
+ "#{top_level.http_path}"
33
+ end
34
+
35
+ def default_http_stylesheets_path
36
+ "#{top_level.http_path}"
37
+ end
38
+
39
+ def default_preferred_syntax
40
+ ::Rails.application.config.sass.preferred_syntax rescue nil
41
+ end
42
+
43
+ def default_sprite_load_path
44
+ CompassRails.sprockets.paths
45
+ end
46
+
47
+ def project_type_without_default
48
+ :rails
49
+ end
50
+
51
+ def default_sass_dir
52
+ File.join("app", "assets", "stylesheets")
53
+ end
54
+
55
+ def default_http_generated_images_path
56
+ # Relies on the fact that this will be loaded after the "normal"
57
+ # defaults, so that method_missing finds http_root_relative
58
+ http_root_relative "images"
59
+ end
60
+
61
+ def default_extensions_dir
62
+ File.join("vendor", "plugins", "compass_extensions")
63
+ end
64
+
65
+ def default_cache_dir
66
+ File.join("tmp", "sass-cache")
67
+ end
68
+
69
+ def default_project_path
70
+ Rails.root
71
+ end
72
+
73
+ def default_environment
74
+ Rails.env
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,33 @@
1
+ require 'compass-rails/patches/compass'
2
+ require 'compass-rails/patches/sass_importer'
3
+ require 'compass-rails/patches/sprite_importer'
4
+
5
+ Compass::Core::SassExtensions::Functions::Urls::GeneratedImageUrl.module_eval do
6
+ def generated_image_url(path, cache_buster = Sass::Script::Bool.new(false))
7
+ cachebust_generated_images(path)
8
+ asset_url(path)
9
+ end
10
+
11
+ def cachebust_generated_images(path)
12
+ generated_images_dir = Compass.configuration.generated_images_dir
13
+ generated_images_dir = Rails.root.join(generated_images_dir)
14
+
15
+ sprockets_env = options[:sprockets][:environment]
16
+ sprockets_entries = sprockets_env.instance_variable_get(:@entries) || {}
17
+ sprockets_stats = sprockets_env.instance_variable_get(:@stats) || {}
18
+
19
+ if sprockets_entries.key?(generated_images_dir.to_s)
20
+ path = path.value
21
+ dir = File.dirname(path)
22
+
23
+ # Delete the entries (directories) which cache the files/dirs in a directory
24
+ entry = generated_images_dir.join(dir).to_s
25
+ sprockets_entries.delete(entry)
26
+
27
+ # Delete the stats (file/dir info) which cache the what kind of file/dir each image is
28
+ stat = generated_images_dir.join(path).to_s
29
+ sprockets_stats.delete(stat)
30
+ end
31
+ end
32
+ end
33
+
@@ -0,0 +1,12 @@
1
+ Compass::Core::SassExtensions::Functions::ImageSize.class_eval do
2
+ private
3
+
4
+ def image_path_for_size(image_file)
5
+ begin
6
+ file = ::Rails.application.assets.find_asset(image_file)
7
+ return file.filename
8
+ rescue ::Sprockets::FileOutsidePaths
9
+ return super(image_file)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,24 @@
1
+ require 'compass/compiler'
2
+ module Compass
3
+ class Compiler
4
+ attr_accessor :sass_options
5
+ STYLESHEET = /stylesheet/
6
+ def sass_options
7
+ @sass_options[:custom] ||= {}
8
+ @sass_options[:custom] = {:resolver => ::Sass::Rails::Resolver.new(CompassRails.context)}
9
+ @sass_options[:load_paths] ||= []
10
+ unless @sass_options[:load_paths].any? {|k| k.is_a?(::Sass::Rails::Importer) }
11
+ ::Rails.application.assets.paths.each do |path|
12
+ next unless path.to_s =~ STYLESHEET
13
+ Dir["#{path}/**/*"].each do |pathname|
14
+ # args are: sprockets environment, the logical_path ex. 'stylesheets', and the full path name for the render
15
+ context = ::CompassRails.context.new(::Rails.application.assets, File.basename(path), Pathname.new(pathname))
16
+ @sass_options[:load_paths] << ::Sass::Rails::Importer.new(context)
17
+ end
18
+ end
19
+ end
20
+ @sass_options
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,90 @@
1
+ klass = if defined?(Sass::Rails::SassTemplate)
2
+ Sass::Rails::SassTemplate
3
+ else
4
+ Sprockets::SassTemplate
5
+ end
6
+
7
+ klass.class_eval do
8
+ def evaluate(context, locals, &block)
9
+ # Use custom importer that knows about Sprockets Caching
10
+ cache_store = Sprockets::SassProcessor::CacheStore.new(sprockets_cache_store, context.environment)
11
+
12
+ paths = context.environment.paths.map { |path| CompassRails::SpriteImporter.new(path) }
13
+ paths += context.environment.paths.map { |path| sass_importer(context, path) }
14
+ paths += ::Rails.application.config.sass.load_paths
15
+
16
+ options = CompassRails.sass_config.merge( {
17
+ :filename => eval_file,
18
+ :line => line,
19
+ :syntax => syntax,
20
+ :cache_store => cache_store,
21
+ :importer => sass_importer(context, context.pathname),
22
+ :load_paths => paths,
23
+ :sprockets => {
24
+ :context => context,
25
+ :environment => context.environment
26
+ }
27
+ })
28
+
29
+ engine = ::Sass::Engine.new(data, options)
30
+
31
+ engine.dependencies.map do |dependency|
32
+ filename = dependency.options[:filename]
33
+ if filename.include?('*') # Handle sprite globs
34
+ image_path = Rails.root.join(Compass.configuration.images_dir).to_s
35
+ Dir[File.join(image_path, filename)].each do |f|
36
+ context.depend_on(f)
37
+ end
38
+ else
39
+ context.depend_on(filename)
40
+ end
41
+ end
42
+
43
+ engine.render
44
+ rescue ::Sass::SyntaxError => e
45
+ # Annotates exception message with parse line number
46
+ context.__LINE__ = e.sass_backtrace.first[:line]
47
+ raise e
48
+ end
49
+
50
+ private
51
+
52
+ def sass_importer_artiy
53
+ @sass_importer_artiy ||= sass_importer_class.instance_method(:initialize).arity
54
+ end
55
+
56
+ def sass_importer(context, path)
57
+ case sass_importer_artiy.abs
58
+ when 1
59
+ sass_importer_class.new(path)
60
+ else
61
+ sass_importer_class.new(context, path)
62
+ end
63
+ end
64
+
65
+ # if using haml-rails, self.class.parent = Haml::Filters (which doesn't have an implementation)
66
+ def sass_importer_class
67
+ @sass_importer_class ||= if defined?(self.class.parent::SassImporter)
68
+ self.class.parent::SassImporter
69
+ elsif defined?(Sass::Rails::SassTemplate)
70
+ Sass::Rails::SassImporter
71
+ else
72
+ Sprockets::SassImporter
73
+ end
74
+ end
75
+
76
+ def sprockets_cache_store
77
+ cache = case Rails.application.config.assets.cache_store
78
+ when :null_store
79
+ Sprockets::Cache::NullStore.new
80
+ when :memory_store, :mem_cache_store
81
+ Sprockets::Cache::MemoryStore.new
82
+ else
83
+ tmpd = Rails.root.join("tmp/compass").to_s
84
+ FileUtils.mkdir(tmpd) unless File.directory?(tmpd)
85
+ Sprockets::Cache::FileStore.new(tmpd)
86
+ end
87
+
88
+ Sprockets::Cache.new(cache, Rails.logger)
89
+ end
90
+ end
@@ -0,0 +1,30 @@
1
+ require 'sprockets'
2
+ require 'compass/sprite_importer'
3
+
4
+ module CompassRails
5
+ class SpriteImporter < Compass::SpriteImporter
6
+ attr_reader :root
7
+
8
+ def initialize(root)
9
+ @root = root
10
+ end
11
+
12
+ def find(uri, options)
13
+ if old = super(uri, options)
14
+ context = options[:sprockets][:context]
15
+ files = self.class.files(uri)
16
+ files.each do |file|
17
+ relative_path = Pathname.new(file).relative_path_from(Pathname.new(root))
18
+ begin
19
+ pathname = context.resolve(relative_path.to_s)
20
+ context.depend_on_asset(pathname)
21
+ rescue Sprockets::FileNotFound
22
+
23
+ end
24
+ end
25
+ end
26
+
27
+ old
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,12 @@
1
+ require 'sprockets/static_compiler'
2
+ module Sprockets
3
+ class StaticCompiler
4
+ cattr_accessor :generated_sprites
5
+ self.generated_sprites = {}
6
+ def write_manifest_with_sprites(manifest)
7
+ write_manifest_without_sprites(manifest.merge(self.class.generated_sprites))
8
+ end
9
+ alias_method_chain :write_manifest, :sprites
10
+ end
11
+ end
12
+
@@ -0,0 +1,51 @@
1
+ module CompassRails
2
+ class Railtie < Rails::Railtie
3
+
4
+ initializer "compass.initialize_rails", :group => :all do |app|
5
+ require 'compass'
6
+ Compass.discover_extensions!
7
+ CompassRails.configure_rails!(app)
8
+ end
9
+
10
+ config.compass = begin
11
+ @compass ||= begin
12
+ data = if (config_file = Compass.detect_configuration_file) && (config_data = Compass.configuration_for(config_file))
13
+ config_data
14
+ else
15
+ Compass::Configuration::Data.new("rails_config")
16
+ end
17
+ data.project_type = :rails # Forcing this makes sure all the rails defaults will be loaded.
18
+ Compass.add_configuration(:rails)
19
+ Compass.add_configuration(data)
20
+ Compass.configuration.on_sprite_saved do |filename|
21
+ if Rails.application.config.assets.digest && # if digesting is enabled
22
+ caller.grep(%r{/sprockets/rails/task.rb}).any? && #OMG HAX - check if we're being precompiled
23
+ Compass.configuration.generated_images_path[Compass.configuration.images_path.to_s]
24
+ # if the generated images path is not in the assets images directory, we don't have to do these backflips
25
+
26
+ # Clear entries in Hike::Index for this sprite's directory.
27
+ # This makes sure the asset can be found by find_assets
28
+ index = Rails.application.assets.index
29
+ index.instance_variable_get(:@entries).delete(File.dirname(filename))
30
+ index.instance_variable_get(:@stats).delete(filename)
31
+
32
+ pathname = Pathname.new(filename)
33
+ logical_path = pathname.relative_path_from(Pathname.new(Compass.configuration.images_path))
34
+ asset = Rails.application.assets.find_asset(logical_path)
35
+ target = File.join(Rails.public_path, Rails.application.config.assets.prefix, asset.digest_path)
36
+
37
+ # Adds the asset to the manifest file.
38
+ manifest = ActionView::Base.assets_manifest
39
+ manifest.assets[logical_path.to_s] = asset.digest_path
40
+
41
+ # Adds the fingerprinted asset to the public directory
42
+ FileUtils.mkdir_p File.dirname(target)
43
+ asset.write_to target
44
+ end
45
+ end
46
+ data
47
+ end
48
+ end
49
+ end
50
+ end
51
+
@@ -0,0 +1,5 @@
1
+ module CompassRails
2
+ unless defined?(::CompassRails::VERSION)
3
+ VERSION = "2.0.4"
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ require 'compass-rails'
@@ -0,0 +1,39 @@
1
+ require 'test_helper'
2
+
3
+ describe CompassRails do
4
+ include CompassRails::Test::RailsHelpers
5
+
6
+ it "compiles a basic compass stylesheet" do
7
+ within_rails_app('test_railtie') do |project|
8
+ project.setup_asset_fixtures!
9
+
10
+ assert project.boots?
11
+
12
+ project.precompile!
13
+
14
+ project.compiled_stylesheet 'public/assets/application*.css' do |css|
15
+ refute css.empty?
16
+ assert_match 'body container', css
17
+ assert_match "-webkit-linear-gradient", css
18
+ assert_match "-moz-border-radius", css
19
+ assert_match '.numbers-sprite-1', css
20
+ assert_match '.numbers-sprite-2', css
21
+ assert_match '.letters-a', css
22
+ assert_match '.letters-a', css
23
+ end
24
+ end
25
+ end
26
+
27
+ it "supports rails config arguments" do
28
+ within_rails_app('test_railtie') do |project|
29
+ assert_equal "scss", project.rails_property("sass.preferred_syntax")
30
+ assert_equal "public/assets", project.rails_property("compass.css_dir")
31
+
32
+ project.set_rails('sass.preferred_syntax', :sass)
33
+ project.set_rails('compass.css_dir', "public/stylesheets")
34
+
35
+ assert_equal "sass", project.rails_property("sass.preferred_syntax")
36
+ assert_equal "public/stylesheets", project.rails_property("compass.css_dir")
37
+ end
38
+ end unless ENV['DEBUG_COMPILE']
39
+ end
File without changes
@@ -0,0 +1,23 @@
1
+ // Import Compass
2
+ @import "compass";
3
+
4
+ // Glob import SCSS partials
5
+ @import "partials/*";
6
+
7
+ // Import Sprites
8
+ @import "letters/*.png";
9
+ @include all-letters-sprites;
10
+
11
+ // Inline Sprites
12
+ $numbers-inline: true;
13
+ @import "numbers/sprite-*.png";
14
+ @include all-numbers-sprites;
15
+
16
+ // Try out some compass stuff
17
+ body{
18
+ @include background-image(linear-gradient(white, #aaaaaa));
19
+
20
+ container{
21
+ @include border-radius(4px, 4px);
22
+ }
23
+ }
@@ -0,0 +1,3 @@
1
+ .partial1 {
2
+ display: none;
3
+ }
@@ -0,0 +1,3 @@
1
+ .partial2{
2
+ display: block;
3
+ }
@@ -0,0 +1,105 @@
1
+ require 'appraisal'
2
+ require 'appraisal/command'
3
+ module Kernal
4
+ module Captures
5
+ def capture_output
6
+ buffer = []
7
+ real_stdout, $stdout = $stdout, StringIO.new
8
+ buffer << yield
9
+ buffer << $stdout.string
10
+ return buffer.join
11
+ ensure
12
+ $stdout = real_stdout
13
+ end
14
+
15
+ def capture_all_output
16
+ capture_output do
17
+ capture_warning do
18
+ yield
19
+ end
20
+ end
21
+ end
22
+
23
+
24
+ def capture_warning
25
+ buffer = []
26
+ real_stderr, $stderr = $stderr, StringIO.new
27
+ buffer << yield
28
+ buffer << $stderr.string
29
+ return buffer.join
30
+ ensure
31
+ $stderr = real_stderr
32
+ end
33
+ end
34
+ end
35
+
36
+ include Kernal::Captures
37
+
38
+ module CompassRails
39
+ module Test
40
+ module CommandHelper
41
+ include DebugHelper
42
+ GEMFILES_DIR = Pathname.new(ROOT_PATH).join('gemfiles')
43
+ BUNDLER_COMMAND = 'bundle'
44
+
45
+ def run_command(command, gemfile=nil)
46
+ debug "Running: #{command} with gemfile: #{gemfile}"
47
+ capture_all_output { CompassRails::Test::CommandRunner.new(command, gemfile).run }
48
+ end
49
+
50
+ def bundle(gemfile=nil)
51
+ run_command(BUNDLER_COMMAND, gemfile)
52
+ end
53
+
54
+ end
55
+ end
56
+ end
57
+
58
+ # Executes commands with a clean environment
59
+ class CompassRails::Test::CommandRunner
60
+ BUNDLER_ENV_VARS = %w(RUBYOPT BUNDLE_PATH BUNDLE_BIN_PATH BUNDLE_GEMFILE).freeze
61
+
62
+ def self.from_args(gemfile)
63
+ command = ([$0] + ARGV.slice(1, ARGV.size)).join(' ')
64
+ new(command, gemfile)
65
+ end
66
+
67
+ def initialize(command, gemfile = nil)
68
+ @original_env = {}
69
+ @gemfile = gemfile
70
+ if command =~ /^bundle/
71
+ @command = command
72
+ else
73
+ @command = "bundle exec #{command}"
74
+ end
75
+ end
76
+
77
+ def run
78
+ with_clean_env { %x{#{@command}} }
79
+ end
80
+
81
+ def exec
82
+ with_clean_env { Kernel.exec(@command) }
83
+ end
84
+
85
+ private
86
+
87
+ def with_clean_env
88
+ unset_bundler_env_vars
89
+ ENV['BUNDLE_GEMFILE'] = @gemfile
90
+ yield
91
+ ensure
92
+ restore_env
93
+ end
94
+
95
+ def unset_bundler_env_vars
96
+ BUNDLER_ENV_VARS.each do |key|
97
+ @original_env[key] = ENV[key]
98
+ ENV[key] = nil
99
+ end
100
+ end
101
+
102
+ def restore_env
103
+ @original_env.each { |key, value| ENV[key] = value }
104
+ end
105
+ end