Generalized application framework integration. There are three that ship with compass: Merb, Rails, and StandAlone.

All application specific behavior is now centralized within the app integration modules.
Plugins can now provide app integration using the --app command line option and by adding the appropriate classes to the compass module tree.
This commit is contained in:
Chris Eppstein 2009-09-01 17:22:26 -07:00
parent 1ea8c9d579
commit cb45b6d438
18 changed files with 362 additions and 321 deletions

View File

@ -1,5 +1,3 @@
# If we're running inside Rails
require File.join(File.dirname(__FILE__), 'app_integration', 'rails') if defined?(ActionController::Base)
# If we're running inside Merb
require File.join(File.dirname(__FILE__), 'app_integration', 'merb') if defined?(Merb::Plugins)
%w(stand_alone rails merb).each do |lib|
require File.join(File.dirname(__FILE__), 'app_integration', lib)
end

View File

@ -1,64 +1 @@
# 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
require File.join(File.dirname(__FILE__), 'merb', 'runtime') if defined?(Merb::Plugins)

View File

@ -0,0 +1,63 @@
# 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,12 +1,8 @@
unless defined?(Compass::RAILS_LOADED)
Compass::RAILS_LOADED = true
require File.join(File.dirname(__FILE__), 'rails', 'action_controller')
require File.join(File.dirname(__FILE__), 'rails', 'sass_plugin')
require File.join(File.dirname(__FILE__), 'rails', 'urls')
# 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
%w(configuration_defaults installer).each do |lib|
require File.join(File.dirname(__FILE__), 'rails', lib)
end
require File.join(File.dirname(__FILE__), 'rails', 'runtime') if defined?(ActionController::Base)

View File

@ -0,0 +1,29 @@
module Compass
module AppIntegration
module Rails
module ConfigurationDefaults
def default_images_dir
File.join("public", "images")
end
def default_javascripts_dir
File.join("public", "javascripts")
end
def default_http_images_path
"/images"
end
def default_http_javascripts_path
"/javascripts"
end
def default_http_stylesheets_path
"/stylesheets"
end
end
end
end
end

View File

@ -0,0 +1,127 @@
module Compass
module Installers
class Base
end
end
module AppIntegration
module Rails
class Installer < Compass::Installers::Base
def default_configuration
Compass::Configuration::Data.new.extend(ConfigurationDefaults)
end
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.config')
write_file config_file, config_contents
write_file targetize('config/initializers/compass.rb'), initializer_contents
end
def config_files_exist?
File.exists?(targetize('config/compass.config')) &&
File.exists?(targetize('config/initializers/compass.rb'))
end
def prepare
write_configuration_files unless config_files_exist?
end
def finalize(options = {})
if options[:create]
puts <<-NEXTSTEPS
Congratulations! Your rails project has been configured to use Compass.
Sass will automatically compile your stylesheets during the next
page request and keep them up to date when they change.
Make sure you restart your server!
NEXTSTEPS
end
if manifest.has_stylesheet?
puts "\nNext add these lines to the head of your layouts:\n\n"
puts stylesheet_links
puts "\n(You are using haml, aren't you?)"
end
end
def install_location_for_html(to, options)
separate("public/#{pattern_name_as_dir}#{to}")
end
def prompt_sass_dir
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 = gets.downcase[0]
answer == ?n ? default_location : recommended_location
end
def prompt_css_dir
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 = gets.downcase[0]
answer == ?n ? default_location : recommended_location
end
def config_contents
Compass.configuration.serialize do |prop, value|
if prop == :project_path
"project_path = RAILS_ROOT if defined?(RAILS_ROOT)\n"
elsif prop == :output_style
""
end
end
end
def initializer_contents
%Q{require 'compass'
# If you have any compass plugins, require them here.
Compass.configuration.parse(File.join(RAILS_ROOT, "config", "compass.config"))
Compass.configuration.environment = RAILS_ENV.to_sym
Compass.configure_sass_plugin!
}
end
def stylesheet_prefix
if css_dir.length >= 19
"#{css_dir[19..-1]}/"
else
nil
end
end
def 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(/\.sass$/,'.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
end
end
end
end

View File

@ -0,0 +1,14 @@
unless defined?(Compass::RAILS_LOADED)
Compass::RAILS_LOADED = true
%w(action_controller sass_plugin urls).each do |lib|
require File.join(File.dirname(__FILE__), 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
end

View File

@ -0,0 +1,3 @@
['configuration_defaults', 'installer'].each do |lib|
require File.join(File.dirname(__FILE__), 'stand_alone', lib)
end

View File

@ -0,0 +1,24 @@
module Compass
module AppIntegration
module StandAlone
module ConfigurationDefaults
def sass_dir_without_default
"src"
end
def javascripts_dir_without_default
"javascripts"
end
def css_dir_without_default
"stylesheets"
end
def images_dir_without_default
"images"
end
end
end
end
end

View File

@ -0,0 +1,71 @@
module Compass
module Installers
class Base
end
end
module AppIntegration
module StandAlone
class Installer < Compass::Installers::Base
def init
directory targetize("")
super
end
def write_configuration_files(config_file = nil)
config_file ||= targetize('config.rb')
write_file config_file, config_contents
end
def config_files_exist?
File.exists? targetize('config.rb')
end
def config_contents
project_path, Compass.configuration.project_path = Compass.configuration.project_path, nil
Compass.configuration.serialize
ensure
Compass.configuration.project_path = project_path
end
def prepare
write_configuration_files unless config_files_exist? || !@manifest.generate_config?
end
def default_configuration
Compass::Configuration::Data.new.extend(Compass::AppIntegration::StandAlone::ConfigurationDefaults)
end
def completed_configuration
nil
end
def finalize(options = {})
if options[:create]
puts <<-NEXTSTEPS
Congratulations! Your compass project has been created.
You must recompile your sass stylesheets when they change.
This can be done in one of the following ways:
1. From within your project directory run:
compass
2. From any directory run:
compass -u path/to/project
3. To monitor your project for changes and automatically recompile:
compass --watch [path/to/project]
NEXTSTEPS
end
if manifest.has_stylesheet?
puts "\nTo import your new stylesheets add the following lines of HTML (or equivalent) to your webpage:"
puts stylesheet_links
end
end
def compilation_required?
@manifest.compile?
end
end
end
end
end

View File

@ -16,14 +16,14 @@ module Compass
end
def installer
@installer ||= case (options[:project_type] || Compass.configuration.project_type)
when :stand_alone
StandAloneInstaller.new *installer_args
when :rails
RailsInstaller.new *installer_args
else
raise "Unknown project type: #{options[:project_type].inspect}"
end
project_type = options[:project_type] || Compass.configuration.project_type
installer_class = "Compass::AppIntegration::#{camelize(project_type)}::Installer"
@installer = eval("#{installer_class}.new *installer_args")
end
# Stolen from ActiveSupport
def camelize(s)
s.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
end
def installer_args

View File

@ -146,10 +146,14 @@ END
self.options[:pattern_name] = name
end
opts.on('--rails', "Sets the project type to a rails project.") do
opts.on('--rails', "Sets the app type to a rails project (same as --app rails).") do
self.options[:project_type] = :rails
end
opts.on('--app APP_TYPE', 'Specify the kind of application to integrate with.') do |project_type|
self.options[:project_type] = project_type.to_sym
end
opts.separator ''
opts.separator 'Configuration Options:'

View File

@ -1,3 +1,3 @@
%w(manifest template_context base stand_alone rails).each do |f|
%w(manifest template_context base).each do |f|
require File.join(File.dirname(__FILE__), 'installers', f)
end

View File

@ -1,144 +0,0 @@
module Compass
module Installers
class RailsInstaller < Base
module ConfigurationDefaults
def default_images_dir
File.join("public", "images")
end
def default_javascripts_dir
File.join("public", "javascripts")
end
def default_http_images_path
"/images"
end
def default_http_javascripts_path
"/javascripts"
end
def default_http_stylesheets_path
"/stylesheets"
end
end
def default_configuration
Compass::Configuration::Data.new.extend(ConfigurationDefaults)
end
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.config')
write_file config_file, config_contents
write_file targetize('config/initializers/compass.rb'), initializer_contents
end
def config_files_exist?
File.exists?(targetize('config/compass.config')) &&
File.exists?(targetize('config/initializers/compass.rb'))
end
def prepare
write_configuration_files unless config_files_exist?
end
def finalize(options = {})
if options[:create]
puts <<-NEXTSTEPS
Congratulations! Your rails project has been configured to use Compass.
Sass will automatically compile your stylesheets during the next
page request and keep them up to date when they change.
Make sure you restart your server!
NEXTSTEPS
end
if manifest.has_stylesheet?
puts "\nNext add these lines to the head of your layouts:\n\n"
puts stylesheet_links
puts "\n(You are using haml, aren't you?)"
end
end
def install_location_for_html(to, options)
separate("public/#{pattern_name_as_dir}#{to}")
end
def prompt_sass_dir
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 = gets.downcase[0]
answer == ?n ? default_location : recommended_location
end
def prompt_css_dir
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 = gets.downcase[0]
answer == ?n ? default_location : recommended_location
end
def config_contents
Compass.configuration.serialize do |prop, value|
if prop == :project_path
"project_path = RAILS_ROOT if defined?(RAILS_ROOT)\n"
elsif prop == :output_style
""
end
end
end
def initializer_contents
%Q{require 'compass'
# If you have any compass plugins, require them here.
Compass.configuration.parse(File.join(RAILS_ROOT, "config", "compass.config"))
Compass.configuration.environment = RAILS_ENV.to_sym
Compass.configure_sass_plugin!
}
end
def stylesheet_prefix
if css_dir.length >= 19
"#{css_dir[19..-1]}/"
else
nil
end
end
def 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(/\.sass$/,'.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
end
end
end

View File

@ -1,83 +0,0 @@
module Compass
module Installers
class StandAloneInstaller < Base
module ConfigurationDefaults
def sass_dir_without_default
"src"
end
def javascripts_dir_without_default
"javascripts"
end
def css_dir_without_default
"stylesheets"
end
def images_dir_without_default
"images"
end
end
def init
directory targetize("")
super
end
def write_configuration_files(config_file = nil)
config_file ||= targetize('config.rb')
write_file config_file, config_contents
end
def config_files_exist?
File.exists? targetize('config.rb')
end
def config_contents
project_path, Compass.configuration.project_path = Compass.configuration.project_path, nil
Compass.configuration.serialize
ensure
Compass.configuration.project_path = project_path
end
def prepare
write_configuration_files unless config_files_exist? || !@manifest.generate_config?
end
def default_configuration
Compass::Configuration::Data.new.extend(ConfigurationDefaults)
end
def completed_configuration
nil
end
def finalize(options = {})
if options[:create]
puts <<-NEXTSTEPS
Congratulations! Your compass project has been created.
You must recompile your sass stylesheets when they change.
This can be done in one of the following ways:
1. From within your project directory run:
compass
2. From any directory run:
compass -u path/to/project
3. To monitor your project for changes and automatically recompile:
compass --watch [path/to/project]
NEXTSTEPS
end
if manifest.has_stylesheet?
puts "\nTo import your new stylesheets add the following lines of HTML (or equivalent) to your webpage:"
puts stylesheet_links
end
end
def compilation_required?
@manifest.compile?
end
end
end
end

View File

@ -17,9 +17,11 @@ module Compass::CommandLineHelper
else
eof_at = nil
timeout(1) do
output << io.readpartial(1024)
partial_output = io.readpartial(1024)
# puts "))))#{partial_output}((((("
output << partial_output
end
prompt = output.split("\n").last
prompt = output.split("\n").last.strip
if response = responder.response_for(prompt)
io.puts response
end

View File

@ -18,8 +18,8 @@ class RailsIntegrationTest < Test::Unit::TestCase
generate_rails_app_directories("compass_rails")
Dir.chdir "compass_rails" do
compass("--rails", '--trace', ".") do |responder|
responder.respond_to "Is this OK? (Y/n) ", :with => "Y", :required => true
responder.respond_to "Emit compiled stylesheets to public/stylesheets/compiled/? (Y/n) ", :with => "Y", :required => true
responder.respond_to "Is this OK? (Y/n)", :with => "Y", :required => true
responder.respond_to "Emit compiled stylesheets to public/stylesheets/compiled/? (Y/n)", :with => "Y", :required => true
end
# puts ">>>#{@last_result}<<<"
assert_action_performed :create, "./app/stylesheets/screen.sass"