Module Sass::Plugin
In: lib/sass/plugin/rack.rb
lib/sass/plugin/configuration.rb
lib/sass/plugin/staleness_checker.rb
lib/sass/plugin.rb
Haml::Util Engine Color SyntaxError UnitConversionError StandardError AbstractSequence CommaSequence Sequence SimpleSequence Simple Parent Universal Class Negation Id Pseudo Attribute Interpolation Element Node Operation Literal UnaryOperation StringInterpolation Funcall Variable Interpolation Lexer CssLexer Number String Bool Parser Parser CssParser EvaluationContext StaticParser SassParser CssParser Node DebugNode IfNode CommentNode ForNode PropNode MixinNode DirectiveNode VariableNode RootNode WarnNode ExtendNode RuleNode MixinDefNode WhileNode Enumerable ImportNode Merb::BootLoader MerbBootLoader Repl CSS Environment Rack StalenessChecker lib/sass/repl.rb lib/sass/css.rb lib/sass/environment.rb lib/sass/error.rb lib/sass/engine.rb lib/sass/selector/simple_sequence.rb lib/sass/selector/abstract_sequence.rb lib/sass/selector/sequence.rb lib/sass/selector/comma_sequence.rb lib/sass/selector/simple.rb lib/sass/selector.rb Selector lib/sass/script/css_parser.rb lib/sass/script/lexer.rb lib/sass/script/color.rb lib/sass/script/string.rb lib/sass/script/unary_operation.rb lib/sass/script/variable.rb lib/sass/script/funcall.rb lib/sass/script/string_interpolation.rb lib/sass/script/operation.rb lib/sass/script/bool.rb lib/sass/script/parser.rb lib/sass/script/node.rb lib/sass/script/literal.rb lib/sass/script/interpolation.rb lib/sass/script/css_lexer.rb lib/sass/script/number.rb lib/sass/script/functions.rb Functions Script lib/sass/scss/sass_parser.rb lib/sass/scss/static_parser.rb lib/sass/scss/parser.rb lib/sass/scss/css_parser.rb ScriptParser ScriptLexer RX SCSS Files Callbacks lib/sass/tree/while_node.rb lib/sass/tree/if_node.rb lib/sass/tree/mixin_def_node.rb lib/sass/tree/debug_node.rb lib/sass/tree/root_node.rb lib/sass/tree/for_node.rb lib/sass/tree/import_node.rb lib/sass/tree/prop_node.rb lib/sass/tree/node.rb lib/sass/tree/comment_node.rb lib/sass/tree/extend_node.rb lib/sass/tree/mixin_node.rb lib/sass/tree/warn_node.rb lib/sass/tree/directive_node.rb lib/sass/tree/rule_node.rb lib/sass/tree/variable_node.rb Tree lib/sass/plugin/rack.rb lib/sass/plugin/staleness_checker.rb lib/sass/plugin/merb.rb Plugin Sass dot/m_61_0.png

This module handles the compilation of Sass/SCSS files. It provides global options and checks whether CSS files need to be updated.

This module is used as the primary interface with Sass when it‘s used as a plugin for various frameworks. All Rack-enabled frameworks are supported out of the box. The plugin is {file:SASS_REFERENCE.md#rails_merb_plugin automatically activated for Rails and Merb}. Other frameworks must enable it explicitly; see {Sass::Plugin::Rack}.

This module has a large set of callbacks available to allow users to run code (such as logging) when certain things happen. All callback methods are of the form `on_#{name}`, and they all take a block that‘s called when the given action occurs.

@example Using a callback Sass::Plugin.on_updating_stylesheet do |template, css|

  puts "Compiling #{template} to #{css}"

end Sass::Plugin.update_stylesheets

  #=> Compiling app/sass/screen.scss to public/stylesheets/screen.css
  #=> Compiling app/sass/print.scss to public/stylesheets/print.css
  #=> Compiling app/sass/ie.scss to public/stylesheets/ie.css

Methods

Included Modules

Sass::Callbacks Haml::Util

Classes and Modules

Class Sass::Plugin::MerbBootLoader
Class Sass::Plugin::Rack
Class Sass::Plugin::StalenessChecker

Attributes

checked_for_updates  [R]  Whether or not Sass has *ever* checked if the stylesheets need to be updated (in this Ruby instance).

@return [Boolean]

options  [R]  An options hash. See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.

@return [{Symbol => Object}]

Public Instance methods

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.

[Source]

     # File lib/sass/plugin/configuration.rb, line 166
166:     def add_template_location(template_location, css_location = options[:css_location])
167:       normalize_template_location!
168:       template_location_array << [template_location, css_location]
169:     end

Same as \{update_stylesheets}, but respects \{checked_for_updates} and the {file:SASS_REFERENCE.md#always_update-option `:always_update`} and {file:SASS_REFERENCE.md#always_check-option `:always_check`} options.

@see update_stylesheets

[Source]

    # File lib/sass/plugin.rb, line 48
48:     def check_for_updates
49:       return unless !Sass::Plugin.checked_for_updates ||
50:           Sass::Plugin.options[:always_update] || Sass::Plugin.options[:always_check]
51:       update_stylesheets
52:     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

[Source]

     # File lib/sass/plugin/configuration.rb, line 145
145:     def engine_options(additional_options = {})
146:       opts = options.dup.merge(additional_options)
147:       opts[:load_paths] = load_paths(opts)
148:       opts
149:     end

Updates all stylesheets, even those that aren‘t out-of-date. Ignores the cache.

@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.

@see update_stylesheets

[Source]

     # File lib/sass/plugin.rb, line 104
104:     def force_update_stylesheets(individual_files = [])
105:       old_options = options
106:       self.options = options.dup
107:       options[:never_update] = false
108:       options[:always_update] = true
109:       options[:cache] = false
110:       update_stylesheets(individual_files)
111:     ensure
112:       self.options = old_options
113:     end

Sets the options hash. See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.

@param value [{Symbol => Object}] The options hash

[Source]

     # File lib/sass/plugin/configuration.rb, line 137
137:     def options=(value)
138:       @options.merge!(value)
139:     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.

[Source]

     # File lib/sass/plugin/configuration.rb, line 192
192:     def remove_template_location(template_location, css_location = options[:css_location])
193:       normalize_template_location!
194:       template_location_array.delete([template_location, css_location])
195:     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.

[Source]

     # File lib/sass/plugin/configuration.rb, line 204
204:     def template_location_array
205:       old_template_location = options[:template_location]
206:       normalize_template_location!
207:       options[:template_location]
208:     ensure
209:       options[:template_location] = old_template_location
210:     end

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.

[Source]

    # File lib/sass/plugin.rb, line 67
67:     def update_stylesheets(individual_files = [])
68:       return if options[:never_update]
69: 
70:       run_updating_stylesheets individual_files
71: 
72:       individual_files.each {|t, c| update_stylesheet(t, c)}
73: 
74:       @checked_for_updates = true
75:       staleness_checker = StalenessChecker.new
76: 
77:       template_location_array.each do |template_location, css_location|
78: 
79:         Dir.glob(File.join(template_location, "**", "*.s[ca]ss")).each do |file|
80:           # Get the relative path to the file
81:           name = file.sub(template_location.sub(/\/*$/, '/'), "")
82:           css = css_filename(name, css_location)
83: 
84:           next if forbid_update?(name)
85:           if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
86:             update_stylesheet file, css
87:           else
88:             run_not_updating_stylesheet file, css
89:           end
90:         end
91:       end
92:     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](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.

[Source]

     # File lib/sass/plugin.rb, line 139
139:     def watch(individual_files = [])
140:       update_stylesheets(individual_files)
141: 
142:       begin
143:         require 'fssm'
144:       rescue LoadError => e
145:         e.message << "\n" <<
146:           if File.exists?(scope(".git"))
147:             'Run "git submodule update --init" to get the recommended version.'
148:           else
149:             'Run "gem install fssm" to get it.'
150:           end
151:         raise e
152:       end
153: 
154:       unless individual_files.empty? && FSSM::Backends::Default.name == "FSSM::Backends::FSEvents"
155:         # As of FSSM 0.1.4, it doesn't support FSevents on individual files,
156:         # but it also isn't smart enough to switch to polling itself.
157:         require 'fssm/backends/polling'
158:         Haml::Util.silence_warnings do
159:           FSSM::Backends.const_set(:Default, FSSM::Backends::Polling)
160:         end
161:       end
162: 
163:       # TODO: Keep better track of what depends on what
164:       # so we don't have to run a global update every time anything changes.
165:       FSSM.monitor do |mon|
166:         template_location_array.each do |template_location, css_location|
167:           mon.path template_location do |path|
168:             path.glob '**/*.s[ac]ss'
169: 
170:             path.update do |base, relative|
171:               run_template_modified File.join(base, relative)
172:               update_stylesheets(individual_files)
173:             end
174: 
175:             path.create do |base, relative|
176:               run_template_created File.join(base, relative)
177:               update_stylesheets(individual_files)
178:             end
179: 
180:             path.delete do |base, relative|
181:               run_template_deleted File.join(base, relative)
182:               css = File.join(css_location, relative.gsub(/\.s[ac]ss$/, '.css'))
183:               try_delete_css css
184:               update_stylesheets(individual_files)
185:             end
186:           end
187:         end
188: 
189:         individual_files.each do |template, css|
190:           mon.file template do |path|
191:             path.update do
192:               run_template_modified template
193:               update_stylesheets(individual_files)
194:             end
195: 
196:             path.create do
197:               run_template_created template
198:               update_stylesheets(individual_files)
199:             end
200: 
201:             path.delete do
202:               run_template_deleted template
203:               try_delete_css css
204:               update_stylesheets(individual_files)
205:             end
206:           end
207:         end
208:       end
209:     end

Private Instance methods

[Source]

     # File lib/sass/plugin.rb, line 253
253:     def css_filename(name, path)
254:       "#{path}/#{name}".gsub(/\.s[ac]ss$/, '.css')
255:     end

[Source]

     # File lib/sass/plugin.rb, line 249
249:     def css_locations
250:       template_location_array.to_a.map {|l| l.last}
251:     end

[Source]

     # File lib/sass/plugin.rb, line 257
257:     def forbid_update?(name)
258:       name.sub(/^.*\//, '')[0] == ?_
259:     end

[Source]

     # File lib/sass/plugin.rb, line 241
241:     def load_paths(opts = options)
242:       (opts[:load_paths] || []) + template_locations
243:     end

[Source]

     # File lib/sass/plugin/configuration.rb, line 214
214:     def normalize_template_location!
215:       return if options[:template_location].is_a?(Array)
216:       options[:template_location] =
217:         case options[:template_location]
218:         when nil; [[File.join(options[:css_location], 'sass'), options[:css_location]]]
219:         when String; [[options[:template_location], options[:css_location]]]
220:         else; options[:template_location].to_a
221:         end
222:     end

Compass expects this to exist

[Source]

     # File lib/sass/plugin.rb, line 262
262:     def stylesheet_needs_update?(css_file, template_file)
263:       StalenessChecker.stylesheet_needs_update?(css_file, template_file)
264:     end

[Source]

     # File lib/sass/plugin.rb, line 245
245:     def template_locations
246:       template_location_array.to_a.map {|l| l.first}
247:     end

[Source]

     # File lib/sass/plugin.rb, line 235
235:     def try_delete_css(css)
236:       return unless File.exists?(css)
237:       run_deleting_css css
238:       File.delete css
239:     end

[Source]

     # File lib/sass/plugin.rb, line 213
213:     def update_stylesheet(filename, css)
214:       dir = File.dirname(css)
215:       unless File.exists?(dir)
216:         run_creating_directory dir
217:         FileUtils.mkdir_p dir
218:       end
219: 
220:       begin
221:         result = Sass::Files.tree_for(filename, engine_options(:css_filename => css, :filename => filename)).render
222:       rescue Exception => e
223:         run_compilation_error e, filename, css
224:         result = Sass::SyntaxError.exception_to_css(e, options)
225:       else
226:         run_updating_stylesheet filename, css
227:       end
228: 
229:       # Finally, write the file
230:       flag = 'w'
231:       flag = 'wb' if RbConfig::CONFIG['host_os'] =~ /mswin|windows/i && options[:unix_newlines]
232:       File.open(css, flag) {|file| file.print(result)}
233:     end

[Validate]