Module Sass::Plugin
In: lib/sass/plugin/configuration.rb
lib/sass/plugin/staleness_checker.rb
lib/sass/plugin/rack.rb
lib/sass/plugin.rb
Haml::Util Engine Color SyntaxError UnitConversionError StandardError AbstractSequence CommaSequence Sequence SimpleSequence Simple Parent Universal Class SelectorPseudoClass Id Pseudo Attribute Interpolation Element Node Operation Literal UnaryOperation StringInterpolation Funcall Interpolation Variable Lexer CssLexer Number Bool String Parser Parser CssParser EvaluationContext SassParser StaticParser CssParser Node DebugNode IfNode CommentNode ForNode PropNode MixinNode DirectiveNode VariableNode RootNode ExtendNode WarnNode WhileNode RuleNode MixinDefNode 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 ScriptLexer ScriptParser 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_63_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 161
161:     def add_template_location(template_location, css_location = options[:css_location])
162:       normalize_template_location!
163:       template_location_array << [template_location, css_location]
164:     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 47
47:     def check_for_updates
48:       return unless !Sass::Plugin.checked_for_updates ||
49:           Sass::Plugin.options[:always_update] || Sass::Plugin.options[:always_check]
50:       update_stylesheets
51:     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 140
140:     def engine_options(additional_options = {})
141:       opts = options.dup.merge(additional_options)
142:       opts[:load_paths] = load_paths(opts)
143:       opts
144:     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 103
103:     def force_update_stylesheets(individual_files = [])
104:       old_options = options
105:       self.options = options.dup
106:       options[:never_update] = false
107:       options[:always_update] = true
108:       options[:cache] = false
109:       update_stylesheets(individual_files)
110:     ensure
111:       self.options = old_options
112:     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 132
132:     def options=(value)
133:       @options.merge!(value)
134:     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 187
187:     def remove_template_location(template_location, css_location = options[:css_location])
188:       normalize_template_location!
189:       template_location_array.delete([template_location, css_location])
190:     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 199
199:     def template_location_array
200:       old_template_location = options[:template_location]
201:       normalize_template_location!
202:       options[:template_location]
203:     ensure
204:       options[:template_location] = old_template_location
205:     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 66
66:     def update_stylesheets(individual_files = [])
67:       return if options[:never_update]
68: 
69:       run_updating_stylesheets individual_files
70: 
71:       individual_files.each {|t, c| update_stylesheet(t, c)}
72: 
73:       @checked_for_updates = true
74:       staleness_checker = StalenessChecker.new
75: 
76:       template_location_array.each do |template_location, css_location|
77: 
78:         Dir.glob(File.join(template_location, "**", "*.s[ca]ss")).sort.each do |file|
79:           # Get the relative path to the file
80:           name = file.sub(template_location.sub(/\/*$/, '/'), "")
81:           css = css_filename(name, css_location)
82: 
83:           next if forbid_update?(name)
84:           if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
85:             update_stylesheet file, css
86:           else
87:             run_not_updating_stylesheet file, css
88:           end
89:         end
90:       end
91:     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 138
138:     def watch(individual_files = [])
139:       update_stylesheets(individual_files)
140: 
141:       begin
142:         require 'fssm'
143:       rescue LoadError => e
144:         e.message << "\n" <<
145:           if File.exists?(scope(".git"))
146:             'Run "git submodule update --init" to get the recommended version.'
147:           else
148:             'Run "gem install fssm" to get it.'
149:           end
150:         raise e
151:       end
152: 
153:       unless individual_files.empty? && FSSM::Backends::Default.name == "FSSM::Backends::FSEvents"
154:         # As of FSSM 0.1.4, it doesn't support FSevents on individual files,
155:         # but it also isn't smart enough to switch to polling itself.
156:         require 'fssm/backends/polling'
157:         Haml::Util.silence_warnings do
158:           FSSM::Backends.const_set(:Default, FSSM::Backends::Polling)
159:         end
160:       end
161: 
162:       # TODO: Keep better track of what depends on what
163:       # so we don't have to run a global update every time anything changes.
164:       FSSM.monitor do |mon|
165:         template_location_array.each do |template_location, css_location|
166:           mon.path template_location do |path|
167:             path.glob '**/*.s[ac]ss'
168: 
169:             path.update do |base, relative|
170:               run_template_modified File.join(base, relative)
171:               update_stylesheets(individual_files)
172:             end
173: 
174:             path.create do |base, relative|
175:               run_template_created File.join(base, relative)
176:               update_stylesheets(individual_files)
177:             end
178: 
179:             path.delete do |base, relative|
180:               run_template_deleted File.join(base, relative)
181:               css = File.join(css_location, relative.gsub(/\.s[ac]ss$/, '.css'))
182:               try_delete_css css
183:               update_stylesheets(individual_files)
184:             end
185:           end
186:         end
187: 
188:         individual_files.each do |template, css|
189:           mon.file template do |path|
190:             path.update do
191:               run_template_modified template
192:               update_stylesheets(individual_files)
193:             end
194: 
195:             path.create do
196:               run_template_created template
197:               update_stylesheets(individual_files)
198:             end
199: 
200:             path.delete do
201:               run_template_deleted template
202:               try_delete_css css
203:               update_stylesheets(individual_files)
204:             end
205:           end
206:         end
207:       end
208:     end

Private Instance methods

[Source]

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

[Source]

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

[Source]

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

[Source]

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

[Source]

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

Compass expects this to exist

[Source]

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

[Source]

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

[Source]

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

[Source]

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

[Validate]