Merge branch 'no_rails_integration'

This commit is contained in:
Scott Davis 2012-01-31 11:55:59 -05:00
commit addbc94716
49 changed files with 605 additions and 1029 deletions

View File

@ -1,6 +1,6 @@
--- ---
:major: 0 :major: 0
:minor: 12 :minor: 12
:state: alpha :state: rc
:build: 4 :build: 4
:name: Alnilam :name: Alnilam

View File

@ -21,6 +21,10 @@ fallback_load_path(File.join(File.dirname(__FILE__), '..', 'lib')) do
require 'compass/exec' require 'compass/exec'
end end
if defined?(Bundler)
Bundler.require :assets
end
runner = Proc.new do runner = Proc.new do
Compass::Exec::SubCommandUI.new(ARGV).run! Compass::Exec::SubCommandUI.new(ARGV).run!
end end

View File

@ -4,15 +4,38 @@ function showInstallCommand() {
var notes = []; var notes = [];
var project_name = "<myproject>"; var project_name = "<myproject>";
var can_be_bare = true; var can_be_bare = true;
commands.push("$ gem install compass"); var in_working_dir = false;
var use_bundler = false;
if ($("#app-type").val() != "rails") {
commands.push("$ gem install compass");
}
if (cmd == "init") { if (cmd == "init") {
commands.push("$ cd " + project_name); commands.push("$ cd " + project_name);
in_working_dir = true
project_name = "."; project_name = ".";
$(".creating").hide();
} else {
$(".creating").show();
if ($("#project_name").val() != "")
project_name = $("#project_name").val();
}
if ($("#app-type").val() == "rails") {
notes.push("<p class='note warning'>Rails 2.3 and 3.0 users require additional installation steps. For full rails installation and upgrade instructions please refer to the compass-rails <a href='https://github.com/Compass/compass-rails/blob/master/README.md'>README</a>.</p>");
use_bundler = true;
} }
if ($("#app-type").val() == "rails") { if ($("#app-type").val() == "rails") {
if (cmd == "create") { if (cmd == "create") {
commands.push("$ rails new " + project_name); commands.push("$ rails new " + project_name);
commands.push("$ cd " + project_name);
in_working_dir = true
project_name = ".";
} }
commands.push("> Edit Gemfile and add this:");
commands.push(" group :assets do");
commands.push(" gem 'compass-rails'");
commands.push(" # Add any compass extensions here");
commands.push(" end");
commands.push("$ bundle");
cmd = "init rails"; cmd = "init rails";
can_be_bare = false; can_be_bare = false;
} else if ($("#app-type").val() == "other") { } else if ($("#app-type").val() == "other") {
@ -28,9 +51,12 @@ function showInstallCommand() {
var framework = $("#framework").val(); var framework = $("#framework").val();
var create_command; var create_command;
if (cmd == "install") { if (cmd == "install") {
create_command = "$ compass install " + framework + " " + project_name; create_command = "$ compass install " + framework;
} else { } else {
create_command = "$ compass " + cmd + " " + project_name; create_command = "$ compass " + cmd;
}
if (!in_working_dir) {
create_command = create_command + " " + project_name;
} }
if (framework != "compass" && framework != "bare" && cmd != "install") { if (framework != "compass" && framework != "bare" && cmd != "install") {
create_command = create_command + " --using " + framework; create_command = create_command + " --using " + framework;
@ -46,14 +72,20 @@ function showInstallCommand() {
} }
if ($("#options").val() == "customized") { if ($("#options").val() == "customized") {
$("#directories").show(); $("#directories").show();
create_command = create_command + if ($("#sassdir").val() != "")
" --sass-dir \"" + $("#sassdir").val() + "\"" + create_command += " --sass-dir \"" + $("#sassdir").val() + "\"";
" --css-dir \"" + $("#cssdir").val() + "\"" + if ($("#cssdir").val() != "")
" --javascripts-dir \"" + $("#jsdir").val() + "\"" + create_command += " --css-dir \"" + $("#cssdir").val() + "\"";
" --images-dir \"" + $("#imagesdir").val() + "\""; if ($("#jsdir").val() != "")
create_command += " --javascripts-dir \"" + $("#jsdir").val() + "\"";
if ($("#imagesdir").val() != "")
create_command += " --images-dir \"" + $("#imagesdir").val() + "\"";
} else { } else {
$("#directories").hide(); $("#directories").hide();
} }
if (use_bundler) {
create_command = "$ bundle exec " + create_command.replace(/\$ /,'');
}
commands.push(create_command); commands.push(create_command);
var instructions = "<pre><code>" + commands.join("\n") + "</code></pre>"; var instructions = "<pre><code>" + commands.join("\n") + "</code></pre>";
if (instructions.match(/&lt;/)) { if (instructions.match(/&lt;/)) {

View File

@ -14,13 +14,23 @@ The Documentation for the [latest stable release](http://compass-style.org/docs/
The Documentation for the [latest preview release](http://beta.compass-style.org/) The Documentation for the [latest preview release](http://beta.compass-style.org/)
0.12.alpha.3 (UNRELEASED) 0.12.rc.0 (UNRELEASED)
------------------------- -------------------------
### Stylesheet Changes
* Removed -ms prefix from box-sizing * Removed -ms prefix from box-sizing
* Added sprite_names sass function * Added sprite_names sass function
* Added -ms prefix to transitions * Added -ms prefix to transitions
* Added support for `--debug-info` and `--no-debug-info` to compass compile
### Command Line
* Added support for `--debug-info` and `--no-debug-info` to the compass compile command
### Rails Integration
Rails projects must now use the [`compass-rails`](https://github.com/compass/compass-rails)
gem to integrate with compass. Please read the [README](https://github.com/Compass/compass-rails/blob/master/README.md) for upgrade instructions. More information in this [blog post](/blog/2012/01/29/compass-and-rails-integration/).
0.12.alpha.3 (12/23/2011) 0.12.alpha.3 (12/23/2011)
------------------------- -------------------------
@ -60,7 +70,7 @@ The Documentation for the [latest preview release](http://beta.compass-style.org
* Changed the descriptions of the sin, cos, and tan to be more descriptive * Changed the descriptions of the sin, cos, and tan to be more descriptive
* Fixed trig functions via issue #498 * Fixed trig functions via issue #498
* Fixed the default `http_path` in rails * Fixed the default `http_path` in rails
* Sprites can now have a `sprite_search_path` that is an array of directories that * Sprites can now have a `sprite_load_path` that is an array of directories that
contain source images for sprites handy for using sprites in extensions or gems contain source images for sprites handy for using sprites in extensions or gems
* Added a new set of configuration properties for generated images. * Added a new set of configuration properties for generated images.
`generated_images_dir`, `generated_images_path`, `http_generated_images_dir`, `generated_images_dir`, `generated_images_path`, `http_generated_images_dir`,

View File

@ -174,10 +174,13 @@ You may also see some real manifest files here:
### Manifest Declarations ### Manifest Declarations
**Easy Mode:** If you just have some basic files and nothing fancy going on, simply place this line in your manifest: **Easy Mode:** If you just have some basic files and nothing fancy going on, simply place this line in your manifest:
discover :all discover :all
If the file is missing `discover :all` is the default
This will cause compass to find all the files in your template and use the files' extension to determine where they should go. Alternatively, you can request that compass only discover files of a certain type. For example, the following will only discover javascript and image assets, you could then declare other file types on your own. This will cause compass to find all the files in your template and use the files' extension to determine where they should go. Alternatively, you can request that compass only discover files of a certain type. For example, the following will only discover javascript and image assets, you could then declare other file types on your own.
discover :javascripts discover :javascripts

View File

@ -30,6 +30,9 @@ body_id: install
%option{:value => "rails"} rails %option{:value => "rails"} rails
%option{:value => "other"} other %option{:value => "other"} other
project project
%span.creating
named
%input#project_name(placeholder="<myproject>")
with with
%select#framework %select#framework
%option{:value => "compass"} compass's %option{:value => "compass"} compass's
@ -48,14 +51,14 @@ body_id: install
%option{:value => "customized"} customize my project's %option{:value => "customized"} customize my project's
directory structure<span id="directories" style="display:none;"> directory structure<span id="directories" style="display:none;">
using using
%input#sassdir(value="sass") %input#sassdir(placeholder="sass")
for the sass source directory, for the sass source directory,
%input#cssdir(value="css") %input#cssdir(placeholder="css")
for the css output directory, for the css output directory,
%input#jsdir(value="javascripts") %input#jsdir(placeholder="javascripts")
for the javascripts directory, for the javascripts directory,
and and
%input#imagesdir(value="images") %input#imagesdir(placeholder="images")
for the images directory</span></span>. for the images directory</span></span>.
%h4 Thanks. Now run the following steps in your terminal: %h4 Thanks. Now run the following steps in your terminal:

View File

@ -0,0 +1,49 @@
---
title: "Compass/Rails Integration in v0.12"
description: "Starting in Compass v0.12 compass's rails integration is
done via a new project called compass-rails."
author: chris
---
The Compass v0.12 release is way behind schedule but it's finally getting
very close to release. The main goal of the v0.12 release has been to add
support for the rails asset pipeline and we hope that you'll agree that this
release achieves the very best integration with rails that compass has
ever provided.
In v0.12, we've create a new gem called `compass-rails` to provide full
support for rails 2.3 and greater. Let me tell you, this was no small
feat. 2.3 lacks Railtie support and 3.1 introduced the asset pipeline.
Backflips were performed; blood, sweat, and tears were shed; Monkeys
were patched and Ducks were punched.
The compass command line tool will now be aware of and compass
configuration settings you've made in your rails configuration files
and/or in the compass configuration file. You can use the approach that
best suites your workflow.
While the asset pipeline is convenient, large applications with lots of
stylesheets and many imports can become sluggish in development mode. To
make things snappier, you can now run the compass watcher in a separate
terminal to begin compilation as soon as you save. In combination with
tools like [live-reload](https://github.com/mockko/livereload), you may
not even need to reload your webpage to see the result in your browser.
Compass extensions and their starter files can be added to your rails
project following the extensions' existing installation instructions.
No special consideration is needed to support rails except to note
that the extension gem should be listed in the `:assets` group of your
Gemfile and you might need to use `bundle exec` to launch the compass
command line tool.
Having a dedicated gem for integration provides a number of benefits.
First, it means that we can release rails integration fixes on a
separate release schedule from the main compass library. Second, it
solves a chicken & egg problem we had where the command-line tools
didn't know whether they were dealing with a rails project until it was
too late. Finally, it allowed us to clean up some of the Compass
internals. To be clear, this gem doesn't mean that Rails support is
deprecated or a second class citizen in any way.
Huge thanks go to [Scott Davis](https://github.com/scottdavis) for his
hard work on the compass-rails gem.

View File

@ -0,0 +1,47 @@
---
title: "Compass v0.12 (Release Candidate) is Released"
description: "Compass 0.12: Flexible Sprites, Rails Integration"
author: chris
---
Compass 0.12 release candidate is out! Install it now:
$ (sudo) gem install compass --pre
This release is primarily to support the Rails Asset Pipeline which
required major changes to the Compass internals. If you use rails
with Compass please read the [blog post about the new compass-rails
gem][compass-rails].
In addition to the rails improvements this release contains many updates
to Compass Sprites:
* **Sprite Layouts**: `vertical` (default), `horizontal`, `diagonal`, and `smart`
layouts are now available. Different layouts may allow you to use
sprites more easily with differing design requirements. The `smart`
layout will efficiently pack sprites of different sizes -- resulting
in smaller file sizes. To select a layout set the
`$<spritename>-layout` variable to your desired layout name.
* **Sprite Load Path**: Sprite source files can now be stored in more locations than
just your images directory. To add sprite locations in your compass
configuration: `sprite_load_path << 'my/sprite/folder'
* **Sprite output location**: If you need to output sprites to a
location other than the images directory set `generated_images_dir`,
`generated_images_path`, `http_generated_images_dir`, and
`http_generated_images_path` in your compass configuration according
to your needs. You can refer to images in your generated images
directory using the `generated-image-url()` function.
Additionally there are many new CSS3 improvements, bug fixes, and other
small enhancements that you can read about in the
[CHANGELOG](/CHANGELOG/).
What's next for Compass? The Sass 3.2 release is coming soon and I'd
very much like the 0.13 release of compass to take advantage of the
great features that it offers. Additionally, we're working on an
extension registry where you can post your compass extensions and
discover new ones. Lastly, we'll be extracting blueprint to a
compass extension as that project seems to have stagnated. I'd say
we're getting pretty close to a 1.0 release!
[compass-rails]: /blog/2012/01/29/compass-and-rails-integration/

View File

@ -77,16 +77,6 @@ Feature: Command Line
Then an error message is printed out: A bare project cannot be created when a framework is specified. Then an error message is printed out: A bare project cannot be created when a framework is specified.
And the command exits with a non-zero error code And the command exits with a non-zero error code
Scenario: Initializing a rails project
Given ruby supports fork
Given I'm in a newly created rails project: my_rails_project
When I initialize a project using: compass init rails --sass-dir app/stylesheets --css-dir public/stylesheets/compiled
Then a config file config/compass.rb is reported created
Then a config file config/compass.rb is created
And a sass file app/stylesheets/screen.scss is created
And a sass file app/stylesheets/print.scss is created
And a sass file app/stylesheets/ie.scss is created
Scenario: Compiling an existing project. Scenario: Compiling an existing project.
Given I am using the existing project in test/fixtures/stylesheets/compass Given I am using the existing project in test/fixtures/stylesheets/compass
When I run: compass compile When I run: compass compile

View File

@ -12,16 +12,6 @@ Feature: Extensions
When I run: compass frameworks When I run: compass frameworks
Then the list of frameworks includes "testing" Then the list of frameworks includes "testing"
@listframeworks
Scenario: Extensions directory for rails projects
Given ruby supports fork
And I'm in a newly created rails project: extension_test_rails_project
And I run: compass init rails
And the "vendor/plugins/compass_extensions" directory exists
And and I have a fake extension at vendor/plugins/compass_extensions/testing
When I run: compass frameworks
Then the list of frameworks includes "testing"
@listframeworks @listframeworks
Scenario: Shared extensions directory Scenario: Shared extensions directory
Given the "~/.compass/extensions" directory exists Given the "~/.compass/extensions" directory exists

View File

@ -1,32 +0,0 @@
Feature: Rails Integration
In order to provide an integrated experience
As a Ruby on Rails user
I want to easily access the Compass functionality
Scenario: Configure Compass from my Application
Given I'm in a rails3.1 application named 'exemplar'
When I edit 'config/application.rb' and save it with the following value:
"""
require File.expand_path('../boot', __FILE__)
require 'rails/all'
Bundler.require(:default, Rails.env) if defined?(Bundler)
module Exemplar
class Application < Rails::Application
config.encoding = "utf-8"
config.filter_parameters += [:password]
config.compass.fonts_dir = "app/assets/fonts"
end
end
"""
And I run: compass config -p fonts_dir
Then the command should print out "app/assets/fonts"
Scenario: Rails gets access to the compass config file
Given I'm in a rails3.1 application named 'exemplar'
When I edit 'config/compass.rb' and save it with the following value:
"""
fonts_dir = "app/assets/fonts"
"""
And I run: ruby -I. -rconfig/environment -e 'puts Compass.configuration.fonts_dir'
Then the command should print out "app/assets/fonts"

View File

@ -6,7 +6,6 @@ require 'compass/exec'
include Compass::TestCaseHelper include Compass::TestCaseHelper
include Compass::CommandLineHelper include Compass::CommandLineHelper
include Compass::IoHelper include Compass::IoHelper
include Compass::RailsHelper
Before do Before do
Compass.reset_configuration! Compass.reset_configuration!
@ -41,17 +40,6 @@ Given %r{^I am in the parent directory$} do
Dir.chdir ".." Dir.chdir ".."
end end
Given %r{^I'm in a newly created rails project: (.+)$} do |project_name|
dir = File.join(Dir.pwd, project_name)
@cleanup_directories << dir
begin
generate_rails_app project_name, Dir.pwd
Dir.chdir dir
rescue LoadError
pending "Missing Ruby-on-rails gems: sudo gem install rails"
end
end
Given /^I should clean up the directory: (\w+)$/ do |directory| Given /^I should clean up the directory: (\w+)$/ do |directory|
@cleanup_directories << directory @cleanup_directories << directory
end end

View File

@ -1,24 +1,39 @@
%w(stand_alone rails merb).each do |lib| require "compass/app_integration/stand_alone"
require "compass/app_integration/#{lib}"
end
module Compass module Compass
module AppIntegration module AppIntegration
module Helpers module Helpers
def lookup(project_type) #attr_accessor :project_types
eval "Compass::AppIntegration::#{camelize(project_type)}" DEAFULT_PROJECT_TYPES = {
rescue NameError :stand_alone => "Compass::AppIntegration::StandAlone"
raise Compass::Error, "No application integration exists for #{project_type}" }
def init
@project_types ||= DEAFULT_PROJECT_TYPES.dup
end end
protected def project_types
@project_types
end
# Stolen from ActiveSupport def default?
def camelize(s) @project_types.keys === DEAFULT_PROJECT_TYPES.keys
s.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase } end
def lookup(type)
unless @project_types[type].nil?
eval @project_types[type]
else
raise Compass::Error, "No application integration exists for #{type}"
end
end
def register(type, klass)
@project_types[type] = klass
end end
end end
extend Helpers extend Helpers
init
end end
end end

View File

@ -1 +0,0 @@
require 'compass/app_integration/merb/runtime' if defined?(Merb::Plugins)

View File

@ -1,63 +0,0 @@
# To configure Merb to use compass do the following:
#
# Add dependencies to config/dependencies.rb
#
# dependency "haml", ">=2.2.0"
# dependency "merb-haml", merb_gems_version
# dependency "chriseppstein-compass", :require_as => 'compass'
#
#
# To use a different sass stylesheets locations as is recommended by compass
# add this configuration to your configuration block:
#
# Merb::BootLoader.before_app_loads do
# Merb::Plugins.config[:compass] = {
# :stylesheets => "app/stylesheets",
# :compiled_stylesheets => "public/stylesheets/compiled"
# }
# end
#
module Compass
def self.setup_template_location
# default the compass configuration if they didn't set it up yet.
Merb::Plugins.config[:compass] ||= {}
# default sass stylesheet location unless configured to something else
Merb::Plugins.config[:compass][:stylesheets] ||= Merb.dir_for(:stylesheet) / "sass"
# default sass css location unless configured to something else
Merb::Plugins.config[:compass][:compiled_stylesheets] ||= Merb.dir_for(:stylesheet)
#define the template hash for the project stylesheets as well as the framework stylesheets.
template_location = {
Merb::Plugins.config[:compass][:stylesheets] => Merb::Plugins.config[:compass][:compiled_stylesheets]
}
Compass::Frameworks::ALL.each do |framework|
template_location[framework.stylesheets_directory] = Merb::Plugins.config[:compass][:compiled_stylesheets]
end
# merge existing template locations if present
if Merb::Plugins.config[:sass][:template_location].is_a?(Hash)
template_location.merge!(Merb::Plugins.config[:sass][:template_location])
Merb::Plugins.config[:sass][:template_location] = template_location
end
#configure Sass to know about all these sass locations.
Sass::Plugin.options[:template_location] = template_location
end
end
Merb::BootLoader.after_app_loads do
#set up sass if haml load didn't do it -- this happens when using a non-default stylesheet location.
unless defined?(Sass::Plugin)
require "sass/plugin"
if Merb::Plugins.config[:sass]
Sass::Plugin.options = Merb::Plugins.config[:sass]
# support old (deprecatd Merb::Config[:sass] option)
elsif Merb::Config[:sass]
Sass::Plugin.options = Merb::Config[:sass]
end
end
Compass.setup_template_location
end

View File

@ -1,83 +0,0 @@
%w(configuration_defaults installer).each do |lib|
require "compass/app_integration/rails/#{lib}"
end
require 'compass/app_integration/rails/runtime' if defined?(ActionController::Base)
module Compass
module AppIntegration
module Rails
extend self
def booted!
Compass::AppIntegration::Rails.const_set(:BOOTED, true)
end
def booted?
defined?(Compass::AppIntegration::Rails::BOOTED) && Compass::AppIntegration::Rails::BOOTED
end
def installer(*args)
Installer.new(*args)
end
def configuration
config = Compass::Configuration::Data.new('rails')
config.extend(ConfigurationDefaults)
config.extend(ConfigurationDefaultsWithAssetPipeline) if Sass::Util.ap_geq?('3.1.0') || Sass::Util.ap_geq?('3.1.0.rc') || Sass::Util.ap_geq?('3.1.0.beta')
config
end
def env
env_production? ? :production : :development
end
def env_production?
if defined?(::Rails) && ::Rails.respond_to?(:env)
::Rails.env.production?
elsif defined?(RAILS_ENV)
RAILS_ENV == "production"
end
end
def root
if defined?(::Rails) && ::Rails.respond_to?(:root)
::Rails.root
elsif defined?(RAILS_ROOT)
RAILS_ROOT
end
end
def check_for_double_boot!
if booted?
Compass::Util.compass_warn("Warning: Compass was booted twice. Compass has a Railtie now; please remove your initializer.")
else
booted!
end
end
def sass_plugin_enabled?
unless Sass::Util.ap_geq?('3.1.0.beta')
defined?(Sass::Plugin) && !Sass::Plugin.options[:never_update]
end
end
def rails_compilation_enabled?
Sass::Util.ap_geq?('3.1.0.beta') && defined?(Sass::Rails) # XXX check if there's some other way(s) to disable the asset pipeline.
end
# Rails 2.x projects use this in their compass initializer.
def initialize!(config = nil)
check_for_double_boot!
config ||= Compass.detect_configuration_file(root)
Compass.add_project_configuration(config, :project_type => :rails)
Compass.discover_extensions!
Compass.configure_sass_plugin!
Compass.handle_configuration_change! if sass_plugin_enabled? || rails_compilation_enabled?
end
end
end
end

View File

@ -1,10 +0,0 @@
%w(action_controller sass_plugin urls).each do |lib|
require "compass/app_integration/rails/actionpack2x/#{lib}"
end
# Wierd that this has to be re-included to pick up sub-modules. Ruby bug?
class Sass::Script::Functions::EvaluationContext
include Sass::Script::Functions
private
include ActionView::Helpers::AssetTagHelper
end

View File

@ -1,15 +0,0 @@
# :stopdoc:
module ActionController
class Base
def process_with_compass(*args)
Sass::Plugin.rails_controller = self
begin
process_without_compass(*args)
ensure
Sass::Plugin.rails_controller = nil
end
end
alias_method_chain :process, :compass
end
end
# :startdoc:

View File

@ -1,5 +0,0 @@
module Sass::Plugin
class << self
attr_accessor :rails_controller
end
end

View File

@ -1,18 +0,0 @@
module Compass::SassExtensions::Functions::Urls::ImageUrl
def image_url_with_rails_integration(path, only_path = Sass::Script::Bool.new(false), cache_buster = Sass::Script::Bool.new(true))
if (@controller = Sass::Plugin.rails_controller) && @controller.respond_to?(:request) && @controller.request
begin
if only_path.to_bool
Sass::Script::String.new image_path(path.value)
else
Sass::Script::String.new "url(#{image_path(path.value)})"
end
ensure
@controller = nil
end
else
image_url_without_rails_integration(path, only_path, cache_buster)
end
end
alias_method_chain :image_url, :rails_integration
end

View File

@ -1,11 +0,0 @@
# TODO figure something out so image_path works with rails integration
%w(railtie).each do |lib|
require "compass/app_integration/rails/actionpack30/#{lib}"
end
# Wierd that this has to be re-included to pick up sub-modules. Ruby bug?
class Sass::Script::Functions::EvaluationContext
include Sass::Script::Functions
private
include ActionView::Helpers::AssetTagHelper
end

View File

@ -1,46 +0,0 @@
require 'compass'
require 'rails'
class Rails::Railtie::Configuration
# Adds compass configuration accessor to the application configuration.
#
# If a configuration file for compass exists, it will be read in and
# the project's configuration values will already be set on the config
# object.
#
# For example:
#
# module MyApp
# class Application < Rails::Application
# config.compass.line_comments = !Rails.env.production?
# config.compass.fonts_dir = "app/assets/fonts"
# end
# end
#
# It is suggested that you create a compass configuration file if you
# want a quicker boot time when using the compass command line tool.
#
# For more information on available configuration options see:
# http://compass-style.org/help/tutorials/configuration-reference/
def compass
@compass ||= begin
data = if (config_file = Compass.detect_configuration_file) && (config_data = Compass.configuration_for(config_file))
config_data
else
Compass::Configuration::Data.new("project")
end
data.project_type = :rails # Forcing this makes sure all the rails defaults will be loaded.
data
end
end
end
module Compass
class Railtie < Rails::Railtie
initializer "compass.initialize_rails" do |app|
# Configure compass for use within rails, and provide the project configuration
# that came via the rails boot process.
Compass::AppIntegration::Rails.initialize!(app.config.compass)
end
end
end

View File

@ -1,5 +0,0 @@
# TODO figure something out so image_path works with rails integration
%w(railtie helpers).each do |lib|
require "compass/app_integration/rails/actionpack31/#{lib}"
end

View File

@ -1,28 +0,0 @@
module Sass::Script::Functions
def generated_image_url(path, only_path = nil)
asset_url(path, Sass::Script::String.new("image"))
end
end
module Compass::RailsImageFunctionPatch
private
def image_path_for_size(image_file)
begin
file = ::Rails.application.assets.find_asset(image_file)
return file
rescue ::Sprockets::FileOutsidePaths
return super(image_file)
end
end
end
module Sass::Script::Functions
include Compass::RailsImageFunctionPatch
end
# Wierd that this has to be re-included to pick up sub-modules. Ruby bug?
class Sass::Script::Functions::EvaluationContext
include Sass::Script::Functions
end

View File

@ -1,87 +0,0 @@
require 'compass'
require 'rails'
class Rails::Railtie::Configuration
# Adds compass configuration accessor to the application configuration.
#
# If a configuration file for compass exists, it will be read in and
# the project's configuration values will already be set on the config
# object.
#
# For example:
#
# module MyApp
# class Application < Rails::Application
# config.compass.line_comments = !Rails.env.production?
# config.compass.fonts_dir = "app/assets/fonts"
# end
# end
#
# It is suggested that you create a compass configuration file if you
# want a quicker boot time when using the compass command line tool.
#
# For more information on available configuration options see:
# http://compass-style.org/help/tutorials/configuration-reference/
def compass
@compass ||= begin
data = if (config_file = Compass.detect_configuration_file) && (config_data = Compass.configuration_for(config_file))
config_data
else
Compass::Configuration::Data.new("rails_config")
end
data.project_type = :rails # Forcing this makes sure all the rails defaults will be loaded.
Compass.add_project_configuration(data)
Compass.configuration.on_sprite_saved do |filename|
# This is a huge hack based on reading through the sprockets internals.
# Sprockets needs an API for adding assets during precompilation.
# At a minimum sprockets should provide this API:
#
# #filename is a path in the asset source directory
# Rails.application.assets.new_asset!(filename)
#
# # logical_path is how devs refer to it, data is the contents of it.
# Rails.application.assets.new_asset!(logical_path, data)
#
# I would also like to select one of the above calls based on whether
# the user is precompiling or not:
#
# Rails.application.assets.precompiling? #=> true or false
#
# But even the above is not an ideal API. The issue is that compass sprites need to
# avoid generation if the sprite file is already generated (which can be quite time
# consuming). To do this, compass has it's own uniqueness hash based on the user's
# inputs instead of being based on the file contents. So if we could provide our own
# hash or some metadata that is opaque to sprockets that could be read from the
# asset's attributes, we could avoid cluttering the assets directory with generated
# sprites and always just use the logical_path + data version of the api.
if Rails.application.config.assets.digests.try(:any?)
asset = Rails.application.assets.find_asset(filename)
pathname = Pathname.new(filename)
logical_path = filename[(Compass.configuration.generated_images_path.length+1)..-1]
# Force the asset into the cache so find_asset will find it.
cached_assets = Rails.application.assets.instance_variable_get("@assets")
cached_assets[logical_path] = cached_assets[filename] = asset
target = Pathname.new(File.join(Rails.public_path, Rails.application.config.assets.prefix))
asset = Rails.application.assets.find_asset(logical_path)
filename = target.join(asset.digest_path)
asset.write_to(filename)
end
end
data
end
@compass
end
end
module Compass
class Railtie < Rails::Railtie
initializer "compass.initialize_rails", :group => :all do |app|
# Configure compass for use within rails, and provide the project configuration
# that came via the rails boot process.
Compass::AppIntegration::Rails.check_for_double_boot!
Compass.discover_extensions!
Compass.configure_rails!(app)
end
end
end

View File

@ -1,123 +0,0 @@
module Compass
module AppIntegration
module Rails
module ConfigurationDefaultsWithAssetPipeline
# These methods overwrite the old rails defaults
# when rails 3.1 is detected.
def default_sass_dir
File.join("app", "assets", "stylesheets")
end
def default_images_dir
File.join("app", "assets", "images")
end
def default_fonts_dir
File.join("app", "assets", "fonts")
end
def default_javascripts_dir
File.join("app", "assets", "javascripts")
end
def default_http_path
::Rails.application.config.assets.prefix
end
def default_http_images_path
"#{top_level.http_path}"
end
def default_http_generated_images_path
"#{top_level.http_path}"
end
def default_http_javascripts_path
"#{top_level.http_path}"
end
def default_http_fonts_path
"#{top_level.http_path}"
end
def default_http_stylesheets_path
"#{top_level.http_path}"
end
end
module ConfigurationDefaults
def project_type_without_default
:rails
end
def default_sass_dir
File.join("app", "stylesheets")
end
def default_css_dir
File.join("public", "stylesheets")
end
def default_images_dir
File.join("public", "images")
end
def default_fonts_dir
File.join("public", "fonts")
end
def default_javascripts_dir
File.join("public", "javascripts")
end
def default_http_images_path
# Relies on the fact that this will be loaded after the "normal"
# defaults, so that method_missing finds http_root_relative
http_root_relative "images"
end
def default_http_generated_images_path
# Relies on the fact that this will be loaded after the "normal"
# defaults, so that method_missing finds http_root_relative
http_root_relative "images"
end
def default_http_javascripts_path
http_root_relative "javascripts"
end
def default_http_fonts_path
http_root_relative "fonts"
end
def default_http_stylesheets_path
http_root_relative "stylesheets"
end
def default_extensions_dir
File.join("vendor", "plugins", "compass_extensions")
end
def default_cache_dir
File.join("tmp", "sass-cache")
end
def default_project_path
project_path = Compass::AppIntegration::Rails.root
end
def default_http_path
"/" # XXX Where is/was this stored in the Rails config?
end
def default_environment
Compass::AppIntegration::Rails.env
end
end
end
end
end

View File

@ -1,182 +0,0 @@
module Compass
module Installers
class Base
end
class ManifestInstaller < Base
end
end
module AppIntegration
module Rails
class Installer < Compass::Installers::ManifestInstaller
def completed_configuration
config = {}
config[:sass_dir] = prompt_sass_dir unless sass_dir_without_default
config[:css_dir] = prompt_css_dir unless css_dir_without_default
config unless config.empty?
end
def write_configuration_files(config_file = nil)
config_file ||= targetize('config/compass.rb')
unless File.exists?(config_file)
directory File.dirname(config_file)
write_file config_file, config_contents
end
unless rails3?
directory File.dirname(targetize('config/initializers/compass.rb'))
write_file targetize('config/initializers/compass.rb'), initializer_contents
end
end
def rails3?
File.exists?(targetize('config/application.rb'))
end
def prepare
write_configuration_files
end
def gem_config_instructions
if rails3?
%Q{Add the following to your Gemfile:\n\n gem "compass", ">= #{Compass::VERSION}"}
else
%Q{Add the following to your environment.rb:\n\n config.gem "compass", :version => ">= #{Compass::VERSION}"}
end
end
def finalize(options = {})
if options[:create]
puts <<-NEXTSTEPS
Congratulations! Your rails project has been configured to use Compass.
Just a couple more things left to do.
#{gem_config_instructions}
Then, make sure you restart your server.
Sass will automatically compile your stylesheets during the next
page request and keep them up to date when they change.
NEXTSTEPS
end
unless options[:prepare]
if manifest.has_stylesheet?
puts "\nNow add these lines to the head of your layout(s):\n\n"
puts stylesheet_links
end
end
end
def hamlize?
# XXX Is there a better way to detect haml in a particular rails project?
require 'haml'
true
rescue LoadError
false
end
def install_location_for_html(to, options)
separate("public/#{pattern_name_as_dir}#{to}")
end
def prompt_sass_dir
if rails3?
nil
else
recommended_location = separate('app/stylesheets')
default_location = separate('public/stylesheets/sass')
print %Q{Compass recommends that you keep your stylesheets in #{recommended_location}
instead of the Sass default location of #{default_location}.
Is this OK? (Y/n) }
answer = $stdin.gets.downcase[0]
answer == ?n ? default_location : recommended_location
end
end
def prompt_css_dir
if rails3?
nil
else
recommended_location = separate("public/stylesheets/compiled")
default_location = separate("public/stylesheets")
puts
print %Q{Compass recommends that you keep your compiled css in #{recommended_location}/
instead the Sass default of #{default_location}/.
However, if you're exclusively using Sass, then #{default_location}/ is recommended.
Emit compiled stylesheets to #{recommended_location}/? (Y/n) }
answer = $stdin.gets
answer = answer.downcase[0]
answer == ?n ? default_location : recommended_location
end
end
def config_contents
project_path, Compass.configuration.project_path = Compass.configuration.project_path, nil
("# This configuration file works with both the Compass command line tool and within Rails.\n" +
Compass.configuration.serialize)
ensure
Compass.configuration.project_path = project_path
end
def initializer_contents
%Q{require 'compass'
|require 'compass/app_integration/rails'
|Compass::AppIntegration::Rails.initialize!
|}.gsub(/^\s+\|/,'')
end
def stylesheet_prefix
if css_dir.length >= 19
"#{css_dir[19..-1]}/"
else
nil
end
end
def stylesheet_links
if hamlize?
haml_stylesheet_links
else
html_stylesheet_links
end
end
def haml_stylesheet_links
html = "%head\n"
manifest.each_stylesheet do |stylesheet|
# Skip partials.
next if File.basename(stylesheet.from)[0..0] == "_"
ss_line = " = stylesheet_link_tag '#{stylesheet_prefix}#{stylesheet.to.sub(/\.s[ac]ss$/,'.css')}'"
if stylesheet.options[:media]
ss_line += ", :media => '#{stylesheet.options[:media]}'"
end
if stylesheet.options[:condition]
ss_line = " /[if #{stylesheet.options[:condition]}]\n " + ss_line
end
html << ss_line + "\n"
end
html
end
def html_stylesheet_links
html = "<head>\n"
manifest.each_stylesheet do |stylesheet|
# Skip partials.
next if File.basename(stylesheet.from)[0..0] == "_"
ss_line = "<%= stylesheet_link_tag '#{stylesheet_prefix}#{stylesheet.to.sub(/\.s[ac]ss$/,'.css')}'"
if stylesheet.options[:media]
ss_line += ", :media => '#{stylesheet.options[:media]}'"
end
ss_line += " %>"
if stylesheet.options[:condition]
ss_line = "<!--[if #{stylesheet.options[:condition]}]>" + ss_line + "<![endif]-->"
end
html << " #{ss_line}\n"
end
html << "</head>"
html
end
end
end
end
end

View File

@ -1,17 +0,0 @@
unless defined?(Compass::RAILS_LOADED)
Compass::RAILS_LOADED = true
begin
require 'action_pack/version'
if ActionPack::VERSION::MAJOR >= 3
if ActionPack::VERSION::MINOR < 1
require 'compass/app_integration/rails/actionpack30'
else
require 'compass/app_integration/rails/actionpack31'
end
else
require 'compass/app_integration/rails/actionpack2x'
end
rescue LoadError, NameError => e
$stderr.puts "Compass could not access the rails environment: #{e}"
end
end

View File

@ -1,78 +0,0 @@
# =================================================================
# Compass Ruby on Rails Installer (template) v.1.0
# written by Derek Perez (derek@derekperez.com)
# -----------------------------------------------------------------
# NOTE: This installer is designed to work as a Rails template,
# and can only be used with Rails 2.3+.
# -----------------------------------------------------------------
# Copyright (c) 2009 Derek Perez
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
# =================================================================
# Determine if we use sudo, defaults to true unless we are
# on win32, cygwin, or mingw32 or they ask us not to
def sudo_is_an_option?
return false if RUBY_PLATFORM =~ /(win|w)32$/ # true if win32, cygwin or mingw32
return false if ENV['NO_SUDO'] =~ /true/i
return true
end
puts "==================================================="
puts "Welcome to the Compass Installer for Ruby on Rails!"
puts "==================================================="
puts
# css framework prompt
css_framework = ask("What CSS Framework install do you want to use with Compass?")
# sass storage prompt
sass_dir = ask("Where would you like to keep your sass files within your project? (default: 'app/stylesheets')")
sass_dir = "app/stylesheets" if Compass::Util.blank?(sass_dir)
# compiled css storage prompt
css_dir = ask("Where would you like Compass to store your compiled css files? (default: 'public/stylesheets/compiled')")
css_dir = "public/stylesheets/compiled" if Compass::Util.blank?(css_dir)
# use sudo for gem commands?
use_sudo = nil
if sudo_is_an_option? # dont give them the option if they are on a system that can't use sudo (aka windows)
use_sudo = yes?("Use sudo for the gem commands? (the default for your system is #{sudo_is_an_option? ? 'yes' : 'no'})")
end
use_sudo = sudo_is_an_option? if Compass::Util.blank?(use_sudo)
# define dependencies
gem "haml", :version => ">=3.0.0"
gem "compass", :version => ">= 0.10.0"
# install and unpack
rake "gems:install GEM=haml --trace", :sudo => use_sudo
rake "gems:install GEM=compass --trace", :sudo => use_sudo
rake "gems:unpack GEM=compass --trace"
# build out compass command
compass_command = "compass init rails . --css-dir=#{css_dir} --sass-dir=#{sass_dir} "
compass_command << "--using #{css_framework} " unless Compass::Util.blank?(css_framework)
# integrate it!
run "haml --rails ."
run compass_command

View File

@ -0,0 +1,93 @@
require 'compass/commands/project_base'
require 'compass/commands/update_project'
module Compass
module Commands
module StructureOptionsParser
def set_options(opts)
opts.banner = %Q{
Usage: compass structure [path/to/project] [options]
Description:
Display the import structure of your stylesheets.
Options:
}.strip.split("\n").map{|l| l.gsub(/^ {0,10}/,'')}.join("\n")
super
end
end
class ProjectStats < UpdateProject
register :structure
def initialize(working_path, options)
super
assert_project_directory_exists!
end
def perform
@compiler = new_compiler_instance
(options[:sass_files] || sorted_sass_files).each do |sass_file|
print_tree(Compass.projectize(sass_file))
end
end
def print_tree(file, depth = 0, importer = @compiler.importer)
puts ((depth > 0 ? "| " : " ") * depth) + "+- " + Compass.deprojectize(file)
@compiler.staleness_checker.send(:compute_dependencies, file, importer).each do |(dep, dep_importer)|
print_tree(dep, depth + 1, dep_importer)# unless Compass.deprojectize(dep)[0...1] == "/"
end
end
def sorted_sass_files
sass_files = @compiler.sass_files
sass_files.map! do |s|
filename = Compass.deprojectize(s, File.join(Compass.configuration.project_path, Compass.configuration.sass_dir))
[s, File.dirname(filename), File.basename(filename)]
end
sass_files = sass_files.sort_by do |s,d,f|
File.join(d, f[0] == ?_ ? f[1..-1] : f)
end
sass_files.map!{|s,d,f| s}
end
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
parser.extend(Compass::Exec::ProjectOptionsParser)
parser.extend(StructureOptionsParser)
end
def usage
option_parser([]).to_s
end
def description(command)
"Report statistics about your stylesheets"
end
def primary; false; end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parse_arguments!(parser, arguments)
parser.options
end
def parse_arguments!(parser, arguments)
if arguments.size > 0
parser.options[:project_name] = arguments.shift if File.directory?(arguments.first)
parser.options[:sass_files] = arguments
end
end
end
end
end
end

View File

@ -81,6 +81,7 @@ module Compass
action = FSSM::Backends::Default.to_s == "FSSM::Backends::Polling" ? "polling" : "watching" action = FSSM::Backends::Default.to_s == "FSSM::Backends::Polling" ? "polling" : "watching"
puts ">>> Compass is #{action} for changes. Press Ctrl-C to Stop." puts ">>> Compass is #{action} for changes. Press Ctrl-C to Stop."
$stdout.flush
begin begin
FSSM.monitor do |monitor| FSSM.monitor do |monitor|
@ -100,14 +101,17 @@ module Compass
path.glob glob path.glob glob
path.update do |base, relative| path.update do |base, relative|
puts ">>> Change detected to: #{relative}" puts ">>> Change detected to: #{relative}"
$stdout.flush
callback.call(base, relative) callback.call(base, relative)
end end
path.create do |base, relative| path.create do |base, relative|
puts ">>> New file detected: #{relative}" puts ">>> New file detected: #{relative}"
$stdout.flush
callback.call(base, relative) callback.call(base, relative)
end end
path.delete do |base, relative| path.delete do |base, relative|
puts ">>> File Removed: #{relative}" puts ">>> File Removed: #{relative}"
$stdout.flush
callback.call(base, relative) callback.call(base, relative)
end end
end end
@ -139,6 +143,7 @@ module Compass
if file = compiler.out_of_date? if file = compiler.out_of_date?
begin begin
puts ">>> Change detected to: #{relative || compiler.relative_stylesheet_name(file)}" puts ">>> Change detected to: #{relative || compiler.relative_stylesheet_name(file)}"
$stdout.flush
compiler.run compiler.run
GC.start GC.start
rescue StandardError => e rescue StandardError => e

View File

@ -37,7 +37,7 @@ module Compass
def stylesheet_name(sass_file) def stylesheet_name(sass_file)
if sass_file.index(from) == 0 if sass_file.index(from) == 0
sass_file[(from.length + 1)..-6] sass_file[(from.length + 1)..-6].sub(/\.css$/,'')
else else
raise Compass::Error, "You must compile individual stylesheets from the project directory." raise Compass::Error, "You must compile individual stylesheets from the project directory."
end end

View File

@ -25,7 +25,6 @@ module Compass
attributes_for_directory(:fonts), attributes_for_directory(:fonts),
attributes_for_directory(:extensions, nil), attributes_for_directory(:extensions, nil),
# Compilation options # Compilation options
:sprite_load_path,
:output_style, :output_style,
:environment, :environment,
:relative_assets, :relative_assets,
@ -44,6 +43,12 @@ module Compass
:chunky_png_options :chunky_png_options
].flatten ].flatten
ARRAY_ATTRIBUTES = [
:sprite_load_path,
:required_libraries,
:loaded_frameworks,
:framework_path
]
# Registers a new configuration property. # Registers a new configuration property.
# Extensions can use this to add new configuration options to compass. # Extensions can use this to add new configuration options to compass.
# #

View File

@ -57,10 +57,11 @@ module Compass
chained_method :run_stylesheet_error chained_method :run_stylesheet_error
inherited_accessor *ATTRIBUTES inherited_accessor *ATTRIBUTES
inherited_accessor :required_libraries, :loaded_frameworks, :framework_path #XXX we should make these arrays add up cumulatively.
strip_trailing_separator *ATTRIBUTES.select{|a| a.to_s =~ /dir|path/} strip_trailing_separator *ATTRIBUTES.select{|a| a.to_s =~ /dir|path/}
inherited_array *ARRAY_ATTRIBUTES
def initialize(name, attr_hash = nil) def initialize(name, attr_hash = nil)
raise "I need a name!" unless name raise "I need a name!" unless name
@name = name @name = name
@ -91,7 +92,9 @@ module Compass
# The block will be passed the root-relative url of the asset. # The block will be passed the root-relative url of the asset.
# When called without a block, returns the block that was previously set. # When called without a block, returns the block that was previously set.
def asset_host(&block) def asset_host(&block)
@set_attributes ||= {}
if block_given? if block_given?
@set_attributes[:asset_host] = true
@asset_host = block @asset_host = block
else else
if @asset_host if @asset_host
@ -116,16 +119,19 @@ module Compass
# #
# asset_cache_buster :none # asset_cache_buster :none
def asset_cache_buster(simple = nil, &block) def asset_cache_buster(simple = nil, &block)
@set_attributes ||= {}
if block_given? if block_given?
@set_attributes[:asset_cache_buster] = true
@asset_cache_buster = block @asset_cache_buster = block
elsif !simple.nil? elsif !simple.nil?
if simple == :none if simple == :none
@set_attributes[:asset_cache_buster] = true
@asset_cache_buster = Proc.new {|_,_| nil} @asset_cache_buster = Proc.new {|_,_| nil}
else else
raise ArgumentError, "Unexpected argument: #{simple.inspect}" raise ArgumentError, "Unexpected argument: #{simple.inspect}"
end end
else else
if @asset_cache_buster if set?(:asset_cache_buster)
@asset_cache_buster @asset_cache_buster
elsif inherited_data.respond_to?(:asset_cache_buster) elsif inherited_data.respond_to?(:asset_cache_buster)
inherited_data.asset_cache_buster inherited_data.asset_cache_buster
@ -173,7 +179,7 @@ module Compass
private private
def assert_valid_keys!(attr_hash) def assert_valid_keys!(attr_hash)
illegal_attrs = attr_hash.keys - ATTRIBUTES illegal_attrs = attr_hash.keys - ATTRIBUTES - ARRAY_ATTRIBUTES
if illegal_attrs.size == 1 if illegal_attrs.size == 1
raise Error, "#{illegal_attrs.first.inspect} is not a valid configuration attribute." raise Error, "#{illegal_attrs.first.inspect} is not a valid configuration attribute."
elsif illegal_attrs.size > 0 elsif illegal_attrs.size > 0

View File

@ -84,13 +84,6 @@ module Compass
end end
end end
def configure_rails!(app)
return unless app.config.respond_to?(:sass)
app.config.compass.to_sass_engine_options.each do |key, value|
app.config.sass.send(:"#{key}=", value)
end
end
def sass_engine_options def sass_engine_options
configuration.to_sass_engine_options configuration.to_sass_engine_options
end end
@ -100,17 +93,8 @@ module Compass
options = args.last.is_a?(Hash) ? args.pop : {} options = args.last.is_a?(Hash) ? args.pop : {}
configuration_file_path = args.shift || detect_configuration_file configuration_file_path = args.shift || detect_configuration_file
# TODO make this better i don't think it belongs here but it gets the job done
# This will allow compass to boot rails and load the config if its configured in the application.rb file via railtie
# if File.exists?(projectize('config/boot.rb')) && configuration_file_path.nil?
# require 'rails'
# require projectize('config/application.rb')
# options[:project_type] = :rails
# end
raise ArgumentError, "Too many arguments" if args.any? raise ArgumentError, "Too many arguments" if args.any?
if data = configuration_for(configuration_file_path, nil, configuration_for(options[:defaults])) if AppIntegration.default? && data = configuration_for(configuration_file_path, nil, configuration_for(options[:defaults]))
if data.raw_project_type if data.raw_project_type
add_configuration(data.raw_project_type.to_sym) add_configuration(data.raw_project_type.to_sym)
elsif options[:project_type] elsif options[:project_type]
@ -119,7 +103,9 @@ module Compass
add_configuration(:stand_alone) add_configuration(:stand_alone)
end end
add_configuration(data) add_configuration(data)
else else
add_configuration(options[:project_type] || configuration.project_type_without_default || (yield if block_given?) || :stand_alone) add_configuration(options[:project_type] || configuration.project_type_without_default || (yield if block_given?) || :stand_alone)
end end

View File

@ -61,6 +61,101 @@ module Compass
inherited_writer(*attributes) inherited_writer(*attributes)
end end
class ArrayProxy
def initialize(data, attr)
@data, @attr = data, attr
end
def to_ary
@data.send(:"read_inherited_#{@attr}_array")
end
def to_a
to_ary
end
def <<(v)
@data.send(:"add_to_#{@attr}", v)
end
def >>(v)
@data.send(:"remove_from_#{@attr}", v)
end
def serialize_to_config(prop)
if v = @data.raw(prop)
"#{prop} = #{v.inspect}"
else
s = ""
if added = @data.instance_variable_get("@added_to_#{@attr}")
added.each do |a|
s << "#{prop} << #{a.inspect}\n"
end
end
if removed = @data.instance_variable_get("@removed_from_#{@attr}")
removed.each do |r|
s << "#{prop} >> #{r.inspect}\n"
end
end
if s[-1..-1] == "\n"
s[0..-2]
else
s
end
end
end
def method_missing(m, *args, &block)
a = to_ary
if a.respond_to?(m)
a.send(m,*args, &block)
else
super
end
end
end
def inherited_array(*attributes)
inherited_reader(*attributes)
inherited_writer(*attributes)
attributes.each do |attr|
line = __LINE__ + 1
class_eval %Q{
def #{attr} # def sprite_load_paths
ArrayProxy.new(self, #{attr.inspect}) # ArrayProxy.new(self, :sprite_load_paths)
end # end
def #{attr}=(value) # def sprite_load_paths=(value)
@set_attributes ||= {} # @set_attributes ||= {}
@set_attributes[#{attr.inspect}] = true # @set_attributes[:sprite_load_paths] = true
@#{attr} = Array(value) # @sprite_load_paths = Array(value)
@added_to_#{attr} = [] # @added_to_sprite_load_paths = []
@removed_from_#{attr} = [] # @removed_from_sprite_load_paths = []
end # end
def read_inherited_#{attr}_array # def read_inherited_sprite_load_paths_array
if #{attr}_set? # if sprite_load_paths_set?
@#{attr} # Array(@#{attr})
else # else
value = if inherited_data # value = Array(read(:sprite_load_paths))
Array(inherited_data.#{attr})
else
Array(read(#{attr.inspect}))
end
value -= Array(@removed_from_#{attr}) # value -= Array(@removed_from_sprite_load_paths)
Array(@added_to_#{attr}) + value # Array(@added_to_sprite_load_paths) + value
end # end
end # end
def add_to_#{attr}(v) # def add_to_sprite_load_paths(v)
if #{attr}_set? # if sprite_load_paths_set?
raw_#{attr} << v # raw_sprite_load_paths << v
else # else
(@added_to_#{attr} ||= []) << v # (@added_to_sprite_load_paths ||= []) << v
end # end
end # end
def remove_from_#{attr}(v) # def remove_from_sprite_load_paths(v)
if #{attr}_set? # if sprite_load_paths_set?
raw_#{attr}.reject!{|e| e == v} # raw_sprite_load_path.reject!{|e| e == v}s
else # else
(@removed_from_#{attr} ||= []) << v # (@removed_from_sprite_load_paths ||= []) << v
end # end
end # end
}, __FILE__, line
end
end
def chained_method(method) def chained_method(method)
line = __LINE__ + 1 line = __LINE__ + 1
class_eval %Q{ class_eval %Q{
@ -146,6 +241,12 @@ module Compass
end end
end end
# Reads the raw value that was set on this object.
# you generally should call raw_<attribute>() instead.
def raw(attribute)
instance_variable_get("@#{attribute}")
end
# Read a value that is either inherited or set on this instance, if we get to the bottom-most configuration instance, # Read a value that is either inherited or set on this instance, if we get to the bottom-most configuration instance,
# we ask for the default starting at the top level. # we ask for the default starting at the top level.
def read(attribute) def read(attribute)

View File

@ -16,13 +16,19 @@ module Compass
end end
end end
def get_binding
binding
end
def parse_string(contents, filename) def parse_string(contents, filename)
bind = binding bind = get_binding
eval(contents, bind, filename) eval(contents, bind, filename)
ATTRIBUTES.each do |prop| local_vars_set = eval("local_variables", bind)
value = eval(prop.to_s, bind) rescue nil local_vars_set.each do |local_var|
value = value.to_s if value.is_a?(Pathname) if (ATTRIBUTES+ARRAY_ATTRIBUTES).include?(local_var.to_sym)
self.send("#{prop}=", value) unless value.nil? value = eval(local_var.to_s, bind)
value = value.to_s if value.is_a?(Pathname)
self.send("#{local_var}=", value)
end
end end
if @added_import_paths if @added_import_paths
self.additional_import_paths ||= [] self.additional_import_paths ||= []
@ -45,7 +51,7 @@ module Compass
end end
contents << "# Require any additional compass plugins here.\n" contents << "# Require any additional compass plugins here.\n"
contents << "\n" if (required_libraries || []).any? contents << "\n" if (required_libraries || []).any?
ATTRIBUTES.each do |prop| (ATTRIBUTES + ARRAY_ATTRIBUTES).each do |prop|
value = send("#{prop}_without_default") value = send("#{prop}_without_default")
if value.is_a?(Proc) if value.is_a?(Proc)
$stderr.puts "WARNING: #{prop} is code and cannot be written to a file. You'll need to copy it yourself." $stderr.puts "WARNING: #{prop} is code and cannot be written to a file. You'll need to copy it yourself."
@ -64,7 +70,11 @@ module Compass
end end
def serialize_property(prop, value) def serialize_property(prop, value)
%Q(#{prop} = #{value.inspect}\n) if value.respond_to?(:serialize_to_config)
value.serialize_to_config(prop) + "\n"
else
%Q(#{prop} = #{value.inspect}\n)
end
end end
def issue_deprecation_warnings def issue_deprecation_warnings

View File

@ -7,4 +7,5 @@ module Compass
class MissingDependency < Error class MissingDependency < Error
end end
class SpriteException < Error; end
end end

View File

@ -141,12 +141,17 @@ module Compass
# evaluated in a Manifest instance context # evaluated in a Manifest instance context
def parse(manifest_file) def parse(manifest_file)
with_manifest(manifest_file) do with_manifest(manifest_file) do
open(manifest_file) do |f| if File.exists?(manifest_file)
eval(f.read, instance_binding, manifest_file) open(manifest_file) do |f|
eval(f.read, instance_binding, manifest_file)
end
else
eval("discover :all", instance_binding, manifest_file)
end end
end end
end end
def instance_binding def instance_binding
binding binding
end end

View File

@ -2,7 +2,6 @@ require 'digest/md5'
require 'compass/sprite_importer' require 'compass/sprite_importer'
module Compass module Compass
class SpriteException < Exception; end
module SassExtensions module SassExtensions
module Sprites module Sprites
end end

View File

@ -26,7 +26,7 @@ module Compass
end end
def find_file def find_file
Compass.configuration.sprite_load_path.each do |path| Compass.configuration.sprite_load_path.compact.each do |path|
f = File.join(path, relative_file) f = File.join(path, relative_file)
if File.exists?(f) if File.exists?(f)
return f return f

View File

@ -74,11 +74,14 @@ module Compass
# Returns the Glob of image files for the uri # Returns the Glob of image files for the uri
def self.files(uri) def self.files(uri)
Compass.configuration.sprite_load_path.each do |folder| Compass.configuration.sprite_load_path.compact.each do |folder|
files = Dir[File.join(folder, uri)].sort files = Dir[File.join(folder, uri)].sort
next if files.empty? next if files.empty?
return files return files
end end
path = Compass.configuration.sprite_load_path.to_a.join(', ')
raise Compass::SpriteException, %Q{No files were found in the load path matching "#{uri}". Your current load paths are: #{path}}
end end
# Returns an Array of image names without the file extension # Returns an Array of image names without the file extension

View File

@ -1,51 +0,0 @@
require 'test_helper'
require 'fileutils'
require 'compass'
require 'compass/exec'
require 'timeout'
class RailsIntegrationTest < Test::Unit::TestCase
include Compass::CommandLineHelper
include Compass::IoHelper
include Compass::RailsHelper
def setup
Compass.reset_configuration!
end
def test_rails_install
within_tmp_directory do
begin
generate_rails_app_directories("compass_rails")
Dir.chdir "compass_rails" do
compass(*%w(init rails --trace --boring .)) do |responder|
responder.respond_to %r{^\s*Is this OK\? \(Y/n\)\s*$}, :with => "Y"
responder.respond_to %r{^\s*Emit compiled stylesheets to public/stylesheets/compiled/\? \(Y/n\)\s*$}, :with => "Y"
end
# puts ">>>#{@last_result}<<<"
assert_action_performed :create, "./app/stylesheets/screen.scss"
assert_action_performed :create, "./config/initializers/compass.rb"
end
ensure
FileUtils.rm_rf "compass_rails"
end
end
rescue LoadError
puts "Skipping rails test. Couldn't Load rails"
rescue NotImplementedError => e
puts "Skipping rails test: #{e}"
end
def test_rails_install_with_no_dialog
within_tmp_directory do
generate_rails_app_directories("compass_rails")
Dir.chdir "compass_rails" do
compass(*%w(init rails --trace --boring --sass-dir app/stylesheets --css-dir public/stylesheets/compiled .))
assert_action_performed :create, "./app/stylesheets/screen.scss"
assert_action_performed :create, "./config/initializers/compass.rb"
end
end
rescue LoadError
puts "Skipping rails test. Couldn't Load rails"
end
end

View File

@ -1,20 +0,0 @@
# XXX This file isn't in use at the moment, but will be used to help test
# XXX deep rails integration of compass features.
need_gems = false
# allows testing with edge Rails by creating a test/rails symlink
RAILS_ROOT = linked_rails = File.dirname(__FILE__) + '/rails'
RAILS_ENV = 'test'
if File.exists?(linked_rails) && !$:.include?(linked_rails + '/activesupport/lib')
puts "[ using linked Rails ]"
$:.unshift linked_rails + '/activesupport/lib'
$:.unshift linked_rails + '/actionpack/lib'
else
need_gems = true
end
require 'rubygems' if need_gems
require 'action_controller'
require 'action_view'

View File

@ -46,8 +46,8 @@ module SpriteHelper
URI = "selectors/*.png" URI = "selectors/*.png"
def init_sprite_helper def init_sprite_helper
@images_src_path = File.join(File.dirname(__FILE__), 'fixtures', 'sprites', 'public', 'images') @images_src_path = File.join(File.expand_path('../', __FILE__), 'fixtures', 'sprites', 'public', 'images')
@images_tmp_path = File.join(File.dirname(__FILE__), 'fixtures', 'sprites', 'public', 'images-tmp') @images_tmp_path = File.join(File.expand_path('../', __FILE__), 'fixtures', 'sprites', 'public', 'images-tmp')
end end
def sprite_map_test(options, uri = URI) def sprite_map_test(options, uri = URI)

View File

@ -0,0 +1,11 @@
require 'test_helper'
require 'fileutils'
class CompilerTest < Test::Unit::TestCase
it "should strip css from file name and reappend" do
compiler = Compass::Compiler.new(Dir.pwd, 'foo', 'bar', {})
assert_equal 'screen', compiler.stylesheet_name(File.join(Dir.pwd, 'foo', 'screen.css.scss'))
end
end

View File

@ -68,6 +68,96 @@ class ConfigurationTest < Test::Unit::TestCase
assert_equal "WARNING: asset_host is code and cannot be written to a file. You'll need to copy it yourself.\n", warning assert_equal "WARNING: asset_host is code and cannot be written to a file. You'll need to copy it yourself.\n", warning
end end
class TestData < Compass::Configuration::Data
def initialize
super(:test)
end
inherited_array :stuff
end
def test_inherited_array_can_clobber
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.stuff = [:b]
data2.inherit_from!(data1)
assert_equal [:b], data2.stuff.to_a
end
def test_inherited_array_can_append
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.stuff << :b
data2.inherit_from!(data1)
assert_equal [:b, :a], data2.stuff.to_a
end
def test_inherited_array_can_append_2
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.stuff << :b
data2.inherit_from!(data1)
data3 = TestData.new
data3.stuff << :c
data3.inherit_from!(data2)
assert_equal [:c, :b, :a], data3.stuff.to_a
end
def test_inherited_array_can_remove
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.stuff >> :a
data2.inherit_from!(data1)
assert_equal [], data2.stuff.to_a
end
def test_inherited_array_combined_augmentations
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.stuff >> :a
data2.stuff << :b
data2.inherit_from!(data1)
assert_equal [:b], data2.stuff.to_a
end
def test_inherited_array_long_methods
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.remove_from_stuff(:a)
data2.add_to_stuff(:b)
data2.inherit_from!(data1)
assert_equal [:b], data2.stuff.to_a
end
def test_inherited_array_augmentations_can_be_clobbered
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.stuff >> :a
data2.stuff << :b
data2.stuff = [:c]
data2.inherit_from!(data1)
assert_equal [:c], data2.stuff.to_a
end
def test_inherited_array_augmentations_after_clobbering
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.stuff >> :a
data2.stuff << :b
data2.stuff = [:c, :d]
data2.stuff << :e
data2.stuff >> :c
data2.inherit_from!(data1)
assert_equal [:d, :e], data2.stuff.to_a
end
def test_serialization_warns_with_asset_cache_buster_set def test_serialization_warns_with_asset_cache_buster_set
contents = StringIO.new(<<-CONFIG) contents = StringIO.new(<<-CONFIG)
asset_cache_buster do |path| asset_cache_buster do |path|
@ -77,12 +167,36 @@ class ConfigurationTest < Test::Unit::TestCase
Compass.add_configuration(contents, "test_serialization_warns_with_asset_cache_buster_set") Compass.add_configuration(contents, "test_serialization_warns_with_asset_cache_buster_set")
assert_kind_of Proc, Compass.configuration.asset_cache_buster_without_default
assert_equal "http://example.com", Compass.configuration.asset_cache_buster_without_default.call("whatever")
warning = capture_warning do warning = capture_warning do
Compass.configuration.serialize Compass.configuration.serialize
end end
assert_equal "WARNING: asset_cache_buster is code and cannot be written to a file. You'll need to copy it yourself.\n", warning assert_equal "WARNING: asset_cache_buster is code and cannot be written to a file. You'll need to copy it yourself.\n", warning
end end
def test_inherited_arrays_augmentations_serialize
inherited = TestData.new
inherited.stuff << :a
d = TestData.new
d.stuff << :b
d.stuff >> :c
assert_equal <<CONFIG, d.serialize_property(:stuff, d.stuff)
stuff << :b
stuff >> :c
CONFIG
end
def test_inherited_arrays_clobbering_with_augmentations_serialize
inherited = TestData.new
inherited.stuff << :a
d = TestData.new
d.stuff << :b
d.stuff = [:c, :d]
d.stuff << :e
assert_equal <<CONFIG, d.serialize_property(:stuff, d.stuff)
stuff = [:c, :d, :e]
CONFIG
end
def test_additional_import_paths def test_additional_import_paths
contents = StringIO.new(<<-CONFIG) contents = StringIO.new(<<-CONFIG)
http_path = "/" http_path = "/"
@ -190,6 +304,36 @@ http_path = \"/\"
# To disable debugging comments that display the original location of your selectors. Uncomment: # To disable debugging comments that display the original location of your selectors. Uncomment:
# line_comments = false # line_comments = false
EXPECTED
assert_correct(expected_serialization, Compass.configuration.serialize)
end
def test_sprite_load_path_clobbers
contents = StringIO.new(<<-CONFIG)
sprite_load_path = ["/Users/chris/Projects/my_compass_project/images/sprites"]
CONFIG
Compass.add_configuration(contents, "test_sass_options")
assert_equal ["/Users/chris/Projects/my_compass_project/images/sprites"], Compass.configuration.sprite_load_path.to_a
expected_serialization = <<EXPECTED
# Require any additional compass plugins here.
# Set this to the root of your project when deployed:
http_path = "/"
# You can select your preferred output style here (can be overridden via the command line):
# output_style = :expanded or :nested or :compact or :compressed
# To enable relative paths to assets via compass helper functions. Uncomment:
# relative_assets = true
# To disable debugging comments that display the original location of your selectors. Uncomment:
# line_comments = false
sprite_load_path = ["/Users/chris/Projects/my_compass_project/images/sprites"]
EXPECTED EXPECTED
assert_correct(expected_serialization, Compass.configuration.serialize) assert_correct(expected_serialization, Compass.configuration.serialize)

View File

@ -1,50 +0,0 @@
require 'test_helper'
require 'compass'
require 'stringio'
class ConfigurationTest < Test::Unit::TestCase
setup do
Compass.reset_configuration!
end
after do
Compass.reset_configuration!
end
def test_defaults
contents = StringIO.new(<<-CONFIG)
project_type = :rails
CONFIG
config = Compass.configuration_for(contents, "config/compass.rb")
Compass.add_project_configuration(config, :project_type => "rails")
assert_equal 'public/images', Compass.configuration.images_dir
assert_equal 'public/stylesheets', Compass.configuration.css_dir
assert_equal 'public/fonts', Compass.configuration.fonts_dir
assert_equal '/', Compass.configuration.http_path
assert_equal '/images', Compass.configuration.http_images_path
assert_equal '/stylesheets', Compass.configuration.http_stylesheets_path
assert_equal '/fonts', Compass.configuration.http_fonts_path
# Other default values must wait until I have a better idea of how to mock Sass::Util.app_geq
end
def test_http_path_change
contents = StringIO.new(<<-CONFIG)
project_type = :rails
http_path = "/test/alternative_path"
CONFIG
config = Compass.configuration_for(contents, "config/compass.rb")
Compass.add_project_configuration(config, :project_type => "rails")
assert_equal '/test/alternative_path', Compass.configuration.http_path
assert_equal '/test/alternative_path/images', Compass.configuration.http_images_path
assert_equal '/test/alternative_path/stylesheets', Compass.configuration.http_stylesheets_path
assert_equal '/test/alternative_path/fonts', Compass.configuration.http_fonts_path
end
end

View File

@ -11,14 +11,15 @@ class SpriteCommandTest < Test::Unit::TestCase
@before_dir = ::Dir.pwd @before_dir = ::Dir.pwd
create_temp_cli_dir create_temp_cli_dir
create_sprite_temp create_sprite_temp
File.open(File.join(@test_dir, 'config.rb'), 'w') do |f| @config_file = File.join(@test_dir, 'config.rb')
File.open(@config_file, 'w') do |f|
f << config_data f << config_data
end end
end end
def config_data def config_data
return <<-CONFIG return <<-CONFIG
images_path = #{@images_tmp_path.inspect} images_path = "#{@images_tmp_path}"
CONFIG CONFIG
end end
@ -47,7 +48,7 @@ class SpriteCommandTest < Test::Unit::TestCase
end end
it "should create sprite file" do it "should create sprite file" do
assert_equal 0, run_compass_with_options(['sprite', "-f", 'stylesheet.scss', "'#{@images_tmp_path}/*.png'"]).to_i assert_equal 0, run_compass_with_options(['sprite', "-f", 'stylesheet.scss', "squares/*.png"]).to_i
assert File.exists?(File.join(test_dir, 'stylesheet.scss')) assert File.exists?(File.join(test_dir, 'stylesheet.scss'))
end end