Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[Sass] Factor out a compiler class from the Plugin module.

  • Loading branch information...
commit 82671fc7419f511f3fcb54eb34b2881be91840f2 1 parent 1feeafb
@chriseppstein chriseppstein authored
View
8 doc-src/SASS_CHANGELOG.md
@@ -119,13 +119,13 @@ can be either a String, a Hash, or an Array.
This makes it difficult to modify or use with confidence.
Thus, three new methods have been added for handling it:
-* {Sass::Plugin#template_location_array} --
+* {Sass::Plugin::Configuration#template_location_array Sass::Plugin#template_location_array} --
Returns the template locations and CSS locations formatted as an array.
-* {Sass::Plugin#add_template_location} --
+* {Sass::Plugin::Configuration#add_template_location Sass::Plugin#add_template_location} --
Converts the template location option to an array and adds a new location.
-* {Sass::Plugin#remove_template_location} --
+* {Sass::Plugin::Configuration#remove_template_location Sass::Plugin#remove_template_location} --
Converts the template location option to an array and removes an existing location.
## 3.0.0
@@ -619,7 +619,7 @@ and all of them will be watched:
sass --watch app/stylesheets:public/stylesheets public/stylesheets/test.sass
File and directory watching is accessible from Ruby,
-using the {Sass::Plugin#watch} function.
+using the {Sass::Plugin::Compiler#watch Sass::Plugin#watch} function.
#### Bulk Updating
View
8 doc-src/SASS_REFERENCE.md
@@ -142,7 +142,7 @@ set the [`:cache`](#cache-option) option to `false`.
### Options
-Options can be set by setting the {Sass::Plugin#options Sass::Plugin.options} hash
+Options can be set by setting the {Sass::Plugin::Configuration#options Sass::Plugin#options} hash
in `environment.rb` in Rails or `config.ru` in Rack...
Sass::Plugin.options[:style] = :compact
@@ -237,9 +237,9 @@ Available options are:
between them.
**Note that due to the many possible formats it can take,
this option should only be set directly, not accessed or modified.
- Use the {Sass::Plugin#template_location_array},
- {Sass::Plugin#add_template_location},
- and {Sass::Plugin#remove_template_location} methods instead**.
+ Use the {Sass::Plugin::Configuration#template_location_array Sass::Plugin#template_location_array},
+ {Sass::Plugin::Configuration#add_template_location Sass::Plugin#add_template_location},
+ and {Sass::Plugin::Configuration#remove_template_location Sass::Plugin#remove_template_location} methods instead**.
{#css_location-option} `:css_location`
: The path where CSS output should be written to.
View
10 lib/sass/callbacks.rb
@@ -23,8 +23,18 @@ module Sass
# m.on_string_munged {|str, res| puts "#{str} was munged into #{res}!"}
# m.munge "bar" #=> bar was munged into bbaarr!
module Callbacks
+ def self.extended(base)
+ base.send(:include, InstanceMethods)
+ end
protected
+ module InstanceMethods
+ # Removes all callbacks registered against this object.
+ def clear_callbacks!
+ @_sass_callbacks = {}
+ end
+ end
+
# Define a callback with the given name.
# This will define an `on_#{name}` method
# that registers a block,
View
190 lib/sass/plugin.rb
@@ -6,8 +6,8 @@
require 'sass/plugin/staleness_checker'
module Sass
- # This module handles the compilation of Sass/SCSS files.
- # It provides global options and checks whether CSS files
+ # This module provides a single interface to the compilation of Sass/SCSS files
+ # for an application. It provides global options and checks whether CSS files
# need to be updated.
#
# This module is used as the primary interface with Sass
@@ -30,7 +30,7 @@ module Sass
# #=> Compiling app/sass/print.scss to public/stylesheets/print.css
# #=> Compiling app/sass/ie.scss to public/stylesheets/ie.css
module Plugin
- include Haml::Util
+ extend self
@checked_for_updates = false
@@ -51,6 +51,13 @@ def check_for_updates
update_stylesheets
end
+ # Returns the singleton compiler instance
+ # This compiler has been pre-configured according
+ # to the plugin configuration.
+ def compiler
+ @compiler ||= Compiler.new
+ end
+
# Updates out-of-date stylesheets.
#
# Checks each Sass/SCSS file in {file:SASS_REFERENCE.md#template_location-option `:template_location`}
@@ -66,29 +73,7 @@ def check_for_updates
# the second is the location of the CSS file that it should be compiled to.
def update_stylesheets(individual_files = [])
return if options[:never_update]
-
- run_updating_stylesheets individual_files
-
- individual_files.each {|t, c| update_stylesheet(t, c)}
-
- @checked_for_updates = true
- staleness_checker = StalenessChecker.new
-
- template_location_array.each do |template_location, css_location|
-
- Dir.glob(File.join(template_location, "**", "*.s[ca]ss")).each do |file|
- # Get the relative path to the file
- name = file.sub(template_location.sub(/\/*$/, '/'), "")
- css = css_filename(name, css_location)
-
- next if forbid_update?(name)
- if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
- update_stylesheet file, css
- else
- run_not_updating_stylesheet file, css
- end
- end
- end
+ compiler.update_stylesheets(individual_files)
end
# Updates all stylesheets, even those that aren't out-of-date.
@@ -112,158 +97,21 @@ def force_update_stylesheets(individual_files = [])
self.options = old_options
end
- # Watches the template directory (or directories)
- # and updates the CSS files whenever the related Sass/SCSS files change.
- # `watch` never returns.
- #
- # Whenever a change is detected to a Sass/SCSS file in
- # {file:SASS_REFERENCE.md#template_location-option `:template_location`},
- # the corresponding CSS file in {file:SASS_REFERENCE.md#css_location-option `:css_location`}
- # will be recompiled.
- # The CSS files of any Sass/SCSS files that import the changed file will also be recompiled.
+ # All other method invocations are proxied to the compiler instance
#
- # Before the watching starts in earnest, `watch` calls \{#update\_stylesheets}.
- #
- # Note that `watch` uses the [FSSM](http://github.com/ttilley/fssm) library
- # to monitor the filesystem for changes.
- # FSSM isn't loaded until `watch` is run.
- # The version of FSSM distributed with Sass is loaded by default,
- # but if another version has already been loaded that will be used instead.
- #
- # @param individual_files [Array<(String, String)>]
- # A list of files to watch for updates
- # **in addition to those specified by the
- # {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
- # The first string in each pair is the location of the Sass/SCSS file,
- # the second is the location of the CSS file that it should be compiled to.
- def watch(individual_files = [])
- update_stylesheets(individual_files)
-
- begin
- require 'fssm'
- rescue LoadError => e
- e.message << "\n" <<
- if File.exists?(scope(".git"))
- 'Run "git submodule update --init" to get the recommended version.'
- else
- 'Run "gem install fssm" to get it.'
- end
- raise e
- end
-
- unless individual_files.empty? && FSSM::Backends::Default.name == "FSSM::Backends::FSEvents"
- # As of FSSM 0.1.4, it doesn't support FSevents on individual files,
- # but it also isn't smart enough to switch to polling itself.
- require 'fssm/backends/polling'
- Haml::Util.silence_warnings do
- FSSM::Backends.const_set(:Default, FSSM::Backends::Polling)
- end
- end
-
- # TODO: Keep better track of what depends on what
- # so we don't have to run a global update every time anything changes.
- FSSM.monitor do |mon|
- template_location_array.each do |template_location, css_location|
- mon.path template_location do |path|
- path.glob '**/*.s[ac]ss'
-
- path.update do |base, relative|
- run_template_modified File.join(base, relative)
- update_stylesheets(individual_files)
- end
-
- path.create do |base, relative|
- run_template_created File.join(base, relative)
- update_stylesheets(individual_files)
- end
-
- path.delete do |base, relative|
- run_template_deleted File.join(base, relative)
- css = File.join(css_location, relative.gsub(/\.s[ac]ss$/, '.css'))
- try_delete_css css
- update_stylesheets(individual_files)
- end
- end
- end
-
- individual_files.each do |template, css|
- mon.file template do |path|
- path.update do
- run_template_modified template
- update_stylesheets(individual_files)
- end
-
- path.create do
- run_template_created template
- update_stylesheets(individual_files)
- end
-
- path.delete do
- run_template_deleted template
- try_delete_css css
- update_stylesheets(individual_files)
- end
- end
- end
- end
- end
-
- private
-
- def update_stylesheet(filename, css)
- dir = File.dirname(css)
- unless File.exists?(dir)
- run_creating_directory dir
- FileUtils.mkdir_p dir
- end
-
- begin
- result = Sass::Files.tree_for(filename, engine_options(:css_filename => css, :filename => filename)).render
- rescue Exception => e
- run_compilation_error e, filename, css
- result = Sass::SyntaxError.exception_to_css(e, options)
+ # @see #compiler
+ # @see Sass::Plugin::Compiler
+ def method_missing(method, *args, &block)
+ if compiler.respond_to?(method)
+ compiler.send(method, *args, &block)
else
- run_updating_stylesheet filename, css
+ super
end
-
- # Finally, write the file
- flag = 'w'
- flag = 'wb' if RbConfig::CONFIG['host_os'] =~ /mswin|windows/i && options[:unix_newlines]
- File.open(css, flag) {|file| file.print(result)}
- end
-
- def try_delete_css(css)
- return unless File.exists?(css)
- run_deleting_css css
- File.delete css
- end
-
- def load_paths(opts = options)
- (opts[:load_paths] || []) + template_locations
- end
-
- def template_locations
- template_location_array.to_a.map {|l| l.first}
- end
-
- def css_locations
- template_location_array.to_a.map {|l| l.last}
- end
-
- def css_filename(name, path)
- "#{path}/#{name}".gsub(/\.s[ac]ss$/, '.css')
end
- def forbid_update?(name)
- name.sub(/^.*\//, '')[0] == ?_
- end
-
- # Compass expects this to exist
- def stylesheet_needs_update?(css_file, template_file)
- StalenessChecker.stylesheet_needs_update?(css_file, template_file)
- end
end
end
+require 'sass/plugin/compiler'
require 'sass/plugin/rails' if defined?(ActionController)
require 'sass/plugin/merb' if defined?(Merb::Plugins)
View
347 lib/sass/plugin/compiler.rb
@@ -0,0 +1,347 @@
+require 'fileutils'
+require 'rbconfig'
+
+require 'sass'
+require 'sass/plugin/configuration'
+require 'sass/plugin/staleness_checker'
+
+module Sass::Plugin
+
+ # The Compiler class provides compilation of
+ # multiple files and/or directories. It is
+ # used by the Sass Plugin module to update
+ # Stylesheets for a single application, but
+ # since it is not a singleton, several compilers
+ # can be created within a single running application.
+ #
+ # If you need to compile a Sass string into CSS,
+ # please see the {Sass::Engine} class.
+ #
+ # Unlike the Sass::Plugin, this class does not have
+ # any logic about how many times to compile or whether
+ # to compile at all. Therefore, the following options
+ # to Sass::Plugin are ignored here (but are handled by
+ # the plugin itself):
+ #
+ # * `:never_update`
+ # * `:always_check`
+ class Compiler
+ include Haml::Util
+ include Configuration
+
+ def initialize(options = {})
+ self.options.merge!(options)
+ end
+
+ extend Sass::Callbacks
+
+ # Register a callback to be run before stylesheets are mass-updated.
+ # This is run whenever \{#update\_stylesheets} is called,
+ # unless the \{file:SASS_REFERENCE.md#never_update-option `:never_update` option}
+ # is enabled.
+ #
+ # @yield [individual_files]
+ # @yieldparam individual_files [<(String, String)>]
+ # Individual files to be updated, in addition to the directories
+ # specified in the options.
+ # The first element of each pair is the source file,
+ # the second is the target CSS file.
+ define_callback :updating_stylesheets
+
+ # Register a callback to be run before a single stylesheet is updated.
+ # The callback is only run if the stylesheet is guaranteed to be updated;
+ # if the CSS file is fresh, this won't be run.
+ #
+ # Even if the \{file:SASS_REFERENCE.md#full_exception-option `:full_exception` option}
+ # is enabled, this callback won't be run
+ # when an exception CSS file is being written.
+ # To run an action for those files, use \{#on\_compilation\_error}.
+ #
+ # @yield [template, css]
+ # @yieldparam template [String]
+ # The location of the Sass/SCSS file being updated.
+ # @yieldparam css [String]
+ # The location of the CSS file being generated.
+ define_callback :updating_stylesheet
+
+ # Register a callback to be run when Sass decides not to update a stylesheet.
+ # In particular, the callback is run when Sass finds that
+ # the template file and none of its dependencies
+ # have been modified since the last compilation.
+ #
+ # Note that this is **not** run when the
+ # \{file:SASS_REFERENCE.md#never-update_option `:never_update` option} is set,
+ # nor when Sass decides not to compile a partial.
+ #
+ # @yield [template, css]
+ # @yieldparam template [String]
+ # The location of the Sass/SCSS file not being updated.
+ # @yieldparam css [String]
+ # The location of the CSS file not being generated.
+ define_callback :not_updating_stylesheet
+
+ # Register a callback to be run when there's an error
+ # compiling a Sass file.
+ # This could include not only errors in the Sass document,
+ # but also errors accessing the file at all.
+ #
+ # @yield [error, template, css]
+ # @yieldparam error [Exception] The exception that was raised.
+ # @yieldparam template [String]
+ # The location of the Sass/SCSS file being updated.
+ # @yieldparam css [String]
+ # The location of the CSS file being generated.
+ define_callback :compilation_error
+
+ # Register a callback to be run when Sass creates a directory
+ # into which to put CSS files.
+ #
+ # Note that even if multiple levels of directories need to be created,
+ # the callback may only be run once.
+ # For example, if "foo/" exists and "foo/bar/baz/" needs to be created,
+ # this may only be run for "foo/bar/baz/".
+ # This is not a guarantee, however;
+ # it may also be run for "foo/bar/".
+ #
+ # @yield [dirname]
+ # @yieldparam dirname [String]
+ # The location of the directory that was created.
+ define_callback :creating_directory
+
+ # Register a callback to be run when Sass detects
+ # that a template has been modified.
+ # This is only run when using \{#watch}.
+ #
+ # @yield [template]
+ # @yieldparam template [String]
+ # The location of the template that was modified.
+ define_callback :template_modified
+
+ # Register a callback to be run when Sass detects
+ # that a new template has been created.
+ # This is only run when using \{#watch}.
+ #
+ # @yield [template]
+ # @yieldparam template [String]
+ # The location of the template that was created.
+ define_callback :template_created
+
+ # Register a callback to be run when Sass detects
+ # that a template has been deleted.
+ # This is only run when using \{#watch}.
+ #
+ # @yield [template]
+ # @yieldparam template [String]
+ # The location of the template that was deleted.
+ define_callback :template_deleted
+
+ # Register a callback to be run when Sass deletes a CSS file.
+ # This happens when the corresponding Sass/SCSS file has been deleted.
+ #
+ # @yield [filename]
+ # @yieldparam filename [String]
+ # The location of the CSS file that was deleted.
+ define_callback :deleting_css
+
+ # Updates out-of-date stylesheets.
+ #
+ # Checks each Sass/SCSS file in {file:SASS_REFERENCE.md#template_location-option `:template_location`}
+ # to see if it's been modified more recently than the corresponding CSS file
+ # in {file:SASS_REFERENCE.md#css_location-option `:css_location`}.
+ # If it has, it updates the CSS file.
+ #
+ # @param individual_files [Array<(String, String)>]
+ # A list of files to check for updates
+ # **in addition to those specified by the
+ # {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
+ # The first string in each pair is the location of the Sass/SCSS file,
+ # the second is the location of the CSS file that it should be compiled to.
+ def update_stylesheets(individual_files = [])
+ run_updating_stylesheets individual_files
+
+ individual_files.each {|t, c| update_stylesheet(t, c)}
+
+ @checked_for_updates = true
+ staleness_checker = StalenessChecker.new
+
+ template_location_array.each do |template_location, css_location|
+
+ Dir.glob(File.join(template_location, "**", "*.s[ca]ss")).each do |file|
+ # Get the relative path to the file
+ name = file.sub(template_location.sub(/\/*$/, '/'), "")
+ css = css_filename(name, css_location)
+
+ next if forbid_update?(name)
+ if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
+ update_stylesheet file, css
+ else
+ run_not_updating_stylesheet file, css
+ end
+ end
+ end
+ end
+
+ # Watches the template directory (or directories)
+ # and updates the CSS files whenever the related Sass/SCSS files change.
+ # `watch` never returns.
+ #
+ # Whenever a change is detected to a Sass/SCSS file in
+ # {file:SASS_REFERENCE.md#template_location-option `:template_location`},
+ # the corresponding CSS file in {file:SASS_REFERENCE.md#css_location-option `:css_location`}
+ # will be recompiled.
+ # The CSS files of any Sass/SCSS files that import the changed file will also be recompiled.
+ #
+ # Before the watching starts in earnest, `watch` calls \{#update\_stylesheets}.
+ #
+ # Note that `watch` uses the [FSSM](http://github.com/ttilley/fssm) library
+ # to monitor the filesystem for changes.
+ # FSSM isn't loaded until `watch` is run.
+ # The version of FSSM distributed with Sass is loaded by default,
+ # but if another version has already been loaded that will be used instead.
+ #
+ # @param individual_files [Array<(String, String)>]
+ # A list of files to watch for updates
+ # **in addition to those specified by the
+ # {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
+ # The first string in each pair is the location of the Sass/SCSS file,
+ # the second is the location of the CSS file that it should be compiled to.
+ def watch(individual_files = [])
+ update_stylesheets(individual_files)
+
+ begin
+ require 'fssm'
+ rescue LoadError => e
+ e.message << "\n" <<
+ if File.exists?(scope(".git"))
+ 'Run "git submodule update --init" to get the recommended version.'
+ else
+ 'Run "gem install fssm" to get it.'
+ end
+ raise e
+ end
+
+ unless individual_files.empty? && FSSM::Backends::Default.name == "FSSM::Backends::FSEvents"
+ # As of FSSM 0.1.4, it doesn't support FSevents on individual files,
+ # but it also isn't smart enough to switch to polling itself.
+ require 'fssm/backends/polling'
+ Haml::Util.silence_warnings do
+ FSSM::Backends.const_set(:Default, FSSM::Backends::Polling)
+ end
+ end
+
+ # TODO: Keep better track of what depends on what
+ # so we don't have to run a global update every time anything changes.
+ FSSM.monitor do |mon|
+ template_location_array.each do |template_location, css_location|
+ mon.path template_location do |path|
+ path.glob '**/*.s[ac]ss'
+
+ path.update do |base, relative|
+ run_template_modified File.join(base, relative)
+ update_stylesheets(individual_files)
+ end
+
+ path.create do |base, relative|
+ run_template_created File.join(base, relative)
+ update_stylesheets(individual_files)
+ end
+
+ path.delete do |base, relative|
+ run_template_deleted File.join(base, relative)
+ css = File.join(css_location, relative.gsub(/\.s[ac]ss$/, '.css'))
+ try_delete_css css
+ update_stylesheets(individual_files)
+ end
+ end
+ end
+
+ individual_files.each do |template, css|
+ mon.file template do |path|
+ path.update do
+ run_template_modified template
+ update_stylesheets(individual_files)
+ end
+
+ path.create do
+ run_template_created template
+ update_stylesheets(individual_files)
+ end
+
+ path.delete do
+ run_template_deleted template
+ try_delete_css css
+ update_stylesheets(individual_files)
+ end
+ end
+ end
+ end
+ end
+
+ # returns options that have been made suitable for
+ # passing to to the Sass::Engine.
+ def engine_options(additional_options = {})
+ opts = options.merge(additional_options)
+ opts[:load_paths] = load_paths(opts)
+ opts
+ end
+
+ private
+
+ def update_stylesheet(filename, css)
+ dir = File.dirname(css)
+ unless File.exists?(dir)
+ run_creating_directory dir
+ FileUtils.mkdir_p dir
+ end
+
+ begin
+ engine_opts = engine_options(:css_filename => css, :filename => filename)
+ result = Sass::Files.tree_for(filename, engine_opts).render
+ rescue Exception => e
+ run_compilation_error e, filename, css
+ result = Sass::SyntaxError.exception_to_css(e, options)
+ else
+ run_updating_stylesheet filename, css
+ end
+
+ # Finally, write the file
+ flag = 'w'
+ flag = 'wb' if RbConfig::CONFIG['host_os'] =~ /mswin|windows/i && options[:unix_newlines]
+ File.open(css, flag) {|file| file.print(result)}
+ end
+
+ def try_delete_css(css)
+ return unless File.exists?(css)
+ run_deleting_css css
+ File.delete css
+ end
+
+ def load_paths(opts = options)
+ (opts[:load_paths] || []) + template_locations
+ end
+
+ def template_locations
+ template_location_array.to_a.map {|l| l.first}
+ end
+
+ def css_locations
+ template_location_array.to_a.map {|l| l.last}
+ end
+
+ def css_filename(name, path)
+ "#{path}/#{name}".gsub(/\.s[ac]ss$/, '.css')
+ end
+
+ def forbid_update?(name)
+ name.sub(/^.*\//, '')[0] == ?_
+ end
+
+ # Compass expects this to exist
+ def stylesheet_needs_update?(css_file, template_file)
+ StalenessChecker.stylesheet_needs_update?(css_file, template_file)
+ end
+ end
+end
+
+require 'sass/plugin/rails' if defined?(ActionController)
+require 'sass/plugin/merb' if defined?(Merb::Plugins)
View
325 lib/sass/plugin/configuration.rb
@@ -1,224 +1,121 @@
# We keep configuration in its own self-contained file
# so that we can load it independently in Rails 3,
# where the full plugin stuff is lazy-loaded.
-
+#
+# XXX CE: is this still necessary now that we have the compiler class?
require 'sass/callbacks'
module Sass
module Plugin
- include Sass::Callbacks
- extend self
-
- # Register a callback to be run before stylesheets are mass-updated.
- # This is run whenever \{#update\_stylesheets} is called,
- # unless the \{file:SASS_REFERENCE.md#never_update-option `:never_update` option}
- # is enabled.
- #
- # @yield [individual_files]
- # @yieldparam individual_files [<(String, String)>]
- # Individual files to be updated, in addition to the directories
- # specified in the options.
- # The first element of each pair is the source file,
- # the second is the target CSS file.
- define_callback :updating_stylesheets
-
- # Register a callback to be run before a single stylesheet is updated.
- # The callback is only run if the stylesheet is guaranteed to be updated;
- # if the CSS file is fresh, this won't be run.
- #
- # Even if the \{file:SASS_REFERENCE.md#full_exception-option `:full_exception` option}
- # is enabled, this callback won't be run
- # when an exception CSS file is being written.
- # To run an action for those files, use \{#on\_compilation\_error}.
- #
- # @yield [template, css]
- # @yieldparam template [String]
- # The location of the Sass/SCSS file being updated.
- # @yieldparam css [String]
- # The location of the CSS file being generated.
- define_callback :updating_stylesheet
-
- # Register a callback to be run when Sass decides not to update a stylesheet.
- # In particular, the callback is run when Sass finds that
- # the template file and none of its dependencies
- # have been modified since the last compilation.
- #
- # Note that this is **not** run when the
- # \{file:SASS_REFERENCE.md#never-update_option `:never_update` option} is set,
- # nor when Sass decides not to compile a partial.
- #
- # @yield [template, css]
- # @yieldparam template [String]
- # The location of the Sass/SCSS file not being updated.
- # @yieldparam css [String]
- # The location of the CSS file not being generated.
- define_callback :not_updating_stylesheet
-
- # Register a callback to be run when there's an error
- # compiling a Sass file.
- # This could include not only errors in the Sass document,
- # but also errors accessing the file at all.
- #
- # @yield [error, template, css]
- # @yieldparam error [Exception] The exception that was raised.
- # @yieldparam template [String]
- # The location of the Sass/SCSS file being updated.
- # @yieldparam css [String]
- # The location of the CSS file being generated.
- define_callback :compilation_error
-
- # Register a callback to be run when Sass creates a directory
- # into which to put CSS files.
- #
- # Note that even if multiple levels of directories need to be created,
- # the callback may only be run once.
- # For example, if "foo/" exists and "foo/bar/baz/" needs to be created,
- # this may only be run for "foo/bar/baz/".
- # This is not a guarantee, however;
- # it may also be run for "foo/bar/".
- #
- # @yield [dirname]
- # @yieldparam dirname [String]
- # The location of the directory that was created.
- define_callback :creating_directory
-
- # Register a callback to be run when Sass detects
- # that a template has been modified.
- # This is only run when using \{#watch}.
- #
- # @yield [template]
- # @yieldparam template [String]
- # The location of the template that was modified.
- define_callback :template_modified
-
- # Register a callback to be run when Sass detects
- # that a new template has been created.
- # This is only run when using \{#watch}.
- #
- # @yield [template]
- # @yieldparam template [String]
- # The location of the template that was created.
- define_callback :template_created
-
- # Register a callback to be run when Sass detects
- # that a template has been deleted.
- # This is only run when using \{#watch}.
- #
- # @yield [template]
- # @yieldparam template [String]
- # The location of the template that was deleted.
- define_callback :template_deleted
-
- # Register a callback to be run when Sass deletes a CSS file.
- # This happens when the corresponding Sass/SCSS file has been deleted.
- #
- # @yield [filename]
- # @yieldparam filename [String]
- # The location of the CSS file that was deleted.
- define_callback :deleting_css
-
- @options = {
- :css_location => './public/stylesheets',
- :always_update => false,
- :always_check => true,
- :full_exception => true
- }
-
- # An options hash.
- # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
- #
- # @return [{Symbol => Object}]
- attr_reader :options
-
- # Sets the options hash.
- # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
- #
- # @param value [{Symbol => Object}] The options hash
- def options=(value)
- @options.merge!(value)
- end
-
- # Non-destructively modifies \{#options} so that default values are properly set.
- #
- # @param additional_options [{Symbol => Object}] An options hash with which to merge \{#options}
- # @return [{Symbol => Object}] The modified options hash
- def engine_options(additional_options = {})
- opts = options.merge(additional_options)
- opts[:load_paths] = load_paths(opts)
- opts
- end
-
- # Adds a new template-location/css-location mapping.
- # This means that Sass/SCSS files in `template_location`
- # will be compiled to CSS files in `css_location`.
- #
- # This is preferred over manually manipulating the {file:SASS_REFERENCE.md#template_location-option `:template_location` option}
- # since the option can be in multiple formats.
- #
- # Note that this method will change `options[:template_location]`
- # to be in the Array format.
- # This means that even if `options[:template_location]`
- # had previously been a Hash or a String,
- # it will now be an Array.
- #
- # @param template_location [String] The location where Sass/SCSS files will be.
- # @param css_location [String] The location where compiled CSS files will go.
- def add_template_location(template_location, css_location = options[:css_location])
- normalize_template_location!
- template_location_array << [template_location, css_location]
- end
-
- # Removes a template-location/css-location mapping.
- # This means that Sass/SCSS files in `template_location`
- # will no longer be compiled to CSS files in `css_location`.
- #
- # This is preferred over manually manipulating the {file:SASS_REFERENCE.md#template_location-option `:template_location` option}
- # since the option can be in multiple formats.
- #
- # Note that this method will change `options[:template_location]`
- # to be in the Array format.
- # This means that even if `options[:template_location]`
- # had previously been a Hash or a String,
- # it will now be an Array.
- #
- # @param template_location [String]
- # The location where Sass/SCSS files were,
- # which is now going to be ignored.
- # @param css_location [String]
- # The location where compiled CSS files went, but will no longer go.
- # @return [Boolean]
- # Non-`nil` if the given mapping already existed and was removed,
- # or `nil` if nothing was changed.
- def remove_template_location(template_location, css_location = options[:css_location])
- normalize_template_location!
- template_location_array.delete([template_location, css_location])
- end
-
- # Returns the template locations configured for Sass
- # as an array of `[template_location, css_location]` pairs.
- # See the {file:SASS_REFERENCE.md#template_location-option `:template_location` option}
- # for details.
- #
- # @return [Array<(String, String)>]
- # An array of `[template_location, css_location]` pairs.
- def template_location_array
- old_template_location = options[:template_location]
- normalize_template_location!
- options[:template_location]
- ensure
- options[:template_location] = old_template_location
- end
-
- private
-
- def normalize_template_location!
- return if options[:template_location].is_a?(Array)
- options[:template_location] =
- case options[:template_location]
- when nil; [[File.join(options[:css_location], 'sass'), options[:css_location]]]
- when String; [[options[:template_location], options[:css_location]]]
- else; options[:template_location].to_a
- end
+ module Configuration
+
+ # Returns the default options for a Sass::Plugin::Compiler
+ def default_options
+ @default_options ||= {
+ :css_location => './public/stylesheets',
+ :always_update => false,
+ :always_check => true,
+ :full_exception => true
+ }.freeze
+ end
+
+ # Resets the options and {Sass::Callbacks::InstanceMethods#clear_callbacks! clears all callbacks}.
+ def reset!
+ @options = nil
+ clear_callbacks!
+ end
+
+ # An options hash.
+ # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
+ #
+ # @return [{Symbol => Object}]
+ def options
+ @options ||= default_options.dup
+ end
+
+ # Sets the options hash.
+ # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
+ # See {Sass::Plugin::Configuration#reset!}
+ # @deprecated Instead, modify the options hash in-place.
+ # @param value [{Symbol => Object}] The options hash
+ def options=(value)
+ Haml::Util.haml_warn("Setting Sass::Plugin.options is deprecated " +
+ "and will be removed in a future release.")
+ options.merge!(value)
+ end
+
+ # Adds a new template-location/css-location mapping.
+ # This means that Sass/SCSS files in `template_location`
+ # will be compiled to CSS files in `css_location`.
+ #
+ # This is preferred over manually manipulating the {file:SASS_REFERENCE.md#template_location-option `:template_location` option}
+ # since the option can be in multiple formats.
+ #
+ # Note that this method will change `options[:template_location]`
+ # to be in the Array format.
+ # This means that even if `options[:template_location]`
+ # had previously been a Hash or a String,
+ # it will now be an Array.
+ #
+ # @param template_location [String] The location where Sass/SCSS files will be.
+ # @param css_location [String] The location where compiled CSS files will go.
+ def add_template_location(template_location, css_location = options[:css_location])
+ normalize_template_location!
+ template_location_array << [template_location, css_location]
+ end
+
+ # Removes a template-location/css-location mapping.
+ # This means that Sass/SCSS files in `template_location`
+ # will no longer be compiled to CSS files in `css_location`.
+ #
+ # This is preferred over manually manipulating the {file:SASS_REFERENCE.md#template_location-option `:template_location` option}
+ # since the option can be in multiple formats.
+ #
+ # Note that this method will change `options[:template_location]`
+ # to be in the Array format.
+ # This means that even if `options[:template_location]`
+ # had previously been a Hash or a String,
+ # it will now be an Array.
+ #
+ # @param template_location [String]
+ # The location where Sass/SCSS files were,
+ # which is now going to be ignored.
+ # @param css_location [String]
+ # The location where compiled CSS files went, but will no longer go.
+ # @return [Boolean]
+ # Non-`nil` if the given mapping already existed and was removed,
+ # or `nil` if nothing was changed.
+ def remove_template_location(template_location, css_location = options[:css_location])
+ normalize_template_location!
+ template_location_array.delete([template_location, css_location])
+ end
+
+ # Returns the template locations configured for Sass
+ # as an array of `[template_location, css_location]` pairs.
+ # See the {file:SASS_REFERENCE.md#template_location-option `:template_location` option}
+ # for details.
+ #
+ # @return [Array<(String, String)>]
+ # An array of `[template_location, css_location]` pairs.
+ def template_location_array
+ old_template_location = options[:template_location]
+ normalize_template_location!
+ options[:template_location]
+ ensure
+ options[:template_location] = old_template_location
+ end
+
+ private
+
+ def normalize_template_location!
+ return if options[:template_location].is_a?(Array)
+ options[:template_location] =
+ case options[:template_location]
+ when nil; [[File.join(options[:css_location], 'sass'), options[:css_location]]]
+ when String; [[options[:template_location], options[:css_location]]]
+ else; options[:template_location].to_a
+ end
+ end
end
end
end
View
37 lib/sass/plugin/merb.rb
@@ -1,21 +1,32 @@
unless defined?(Sass::MERB_LOADED)
Sass::MERB_LOADED = true
- version = Merb::VERSION.split('.').map { |n| n.to_i }
- if version[0] <= 0 && version[1] < 5
- root = MERB_ROOT
- env = MERB_ENV
- else
- root = Merb.root.to_s
- env = Merb.environment
+ module Sass::Plugin::Configuration
+ # Different default options in a m envirionment.
+ def default_options
+ @default_options ||= begin
+ version = Merb::VERSION.split('.').map { |n| n.to_i }
+ if version[0] <= 0 && version[1] < 5
+ root = MERB_ROOT
+ env = MERB_ENV
+ else
+ root = Merb.root.to_s
+ env = Merb.environment
+ end
+
+ {
+ :always_update => false,
+ :template_location => root + '/public/stylesheets/sass',
+ :css_location => root + '/public/stylesheets',
+ :cache_location => root + '/tmp/sass-cache',
+ :always_check => env != "production",
+ :quiet => env != "production",
+ :full_exception => env != "production"
+ }.freeze
+ end
+ end
end
- Sass::Plugin.options.merge!(:template_location => root + '/public/stylesheets/sass',
- :css_location => root + '/public/stylesheets',
- :cache_location => root + '/tmp/sass-cache',
- :always_check => env != "production",
- :quiet => env != "production",
- :full_exception => env != "production")
config = Merb::Plugins.config[:sass] || Merb::Plugins.config["sass"] || {}
if defined? config.symbolize_keys!
View
23 lib/sass/plugin/rails.rb
@@ -1,13 +1,22 @@
unless defined?(Sass::RAILS_LOADED)
Sass::RAILS_LOADED = true
- # Reverse-merging (we're in Rails, anyway) so we dont' clobber what's already been defined further up-stream
- Sass::Plugin.options.reverse_merge!(:template_location => Haml::Util.rails_root + '/public/stylesheets/sass',
- :css_location => Haml::Util.rails_root + '/public/stylesheets',
- :cache_location => Haml::Util.rails_root + '/tmp/sass-cache',
- :always_check => Haml::Util.rails_env == "development",
- :quiet => Haml::Util.rails_env != "production",
- :full_exception => Haml::Util.rails_env != "production")
+ module Sass::Plugin::Configuration
+ # Different default options in a rails envirionment.
+ def default_options
+ @default_options ||= {
+ :always_update => false,
+ :template_location => Haml::Util.rails_root + '/public/stylesheets/sass',
+ :css_location => Haml::Util.rails_root + '/public/stylesheets',
+ :cache_location => Haml::Util.rails_root + '/tmp/sass-cache',
+ :always_check => Haml::Util.rails_env == "development",
+ :quiet => Haml::Util.rails_env != "production",
+ :full_exception => Haml::Util.rails_env != "production"
+ }.freeze
+ end
+ end
+
+ Sass::Plugin.options.reverse_merge!(Sass::Plugin.default_options)
if defined?(ActionController::Metal)
# Rails >= 3.0
View
12 test/sass/plugin_test.rb
@@ -20,7 +20,7 @@ def setup
def teardown
clean_up_sassc
- clear_callbacks
+ Sass::Plugin.reset!
FileUtils.rm_r tempfile_loc
FileUtils.rm_r tempfile_loc(nil,"more_")
end
@@ -342,10 +342,6 @@ def assert_no_callbacks(*args)
assert_no_callback(*args.pop) {assert_no_callbacks(*args)}
end
- def clear_callbacks
- Sass::Plugin.instance_variable_set('@_sass_callbacks', {})
- end
-
def update_all_stylesheets!
Haml::Util.silence_haml_warnings do
Sass::Plugin.update_stylesheets
@@ -403,14 +399,16 @@ def absolutize(file)
end
def set_plugin_opts(overrides = {})
- Sass::Plugin.options = {
+ Sass::Plugin.options.merge!(
:template_location => template_loc,
:css_location => tempfile_loc,
:style => :compact,
:load_paths => [result_loc],
:always_update => true,
:never_update => false,
- }.merge(overrides)
+ :full_exception => true
+ )
+ Sass::Plugin.options.merge!(overrides)
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.