Class: Sass::Plugin::Compiler
- Inherits:
-
Object
- Object
- Sass::Plugin::Compiler
- Extended by:
- Callbacks
- Includes:
- Configuration
- Defined in:
- lib/sass/plugin/compiler.rb
Overview
The Compiler class handles compilation of multiple files and/or directories, including checking which CSS files are out-of-date and need to be updated and calling Sass to perform the compilation on those files.
Sass::Plugin uses this class to update stylesheets for a single application. Unlike Sass::Plugin, though, the Compiler class has no global state, and so multiple instances may be created and used independently.
If you need to compile a Sass string into CSS, please see the Engine class.
Unlike Sass::Plugin, this class doesn't keep track of
whether or how many times a stylesheet should be updated.
Therefore, the following Sass::Plugin
options are ignored by the Compiler:
:never_update
:always_check
Instance Method Summary collapse
-
#clean(individual_files = [])
Remove all output files that would be created by calling update_stylesheets, if they exist.
-
#engine_options(additional_options = {}) ⇒ {Symbol => Object}
Non-destructively modifies Sass::Plugin::Configuration#options so that default values are properly set, and returns the result.
-
#file_list(individual_files = []) ⇒ Array<(String, String, String)>
Construct a list of files that might need to be compiled from the provided individual_files and the template_locations.
-
#initialize(opts = {}) ⇒ Compiler
constructor
Creates a new compiler.
-
#stylesheet_needs_update?(css_file, template_file) ⇒ Boolean
Compass expects this to exist.
-
#update_stylesheets(individual_files = [])
Updates out-of-date stylesheets.
-
#watch(individual_files = [], options = {})
Watches the template directory (or directories) and updates the CSS files whenever the related Sass/SCSS files change.
Methods included from Callbacks
Methods included from Configuration
#add_template_location, #default_options, #options, #remove_template_location, #reset!, #template_location_array
Constructor Details
#initialize(opts = {}) ⇒ Compiler
Creates a new compiler.
35 36 37 38 |
# File 'lib/sass/plugin/compiler.rb', line 35
def initialize(opts = {})
@watched_files = Set.new
options.merge!(opts)
end
|
Instance Method Details
#clean(individual_files = [])
Remove all output files that would be created by calling update_stylesheets, if they exist.
This method runs the deleting_css and deleting_sourcemap callbacks for the files that are deleted.
362 363 364 365 366 367 368 369 370 371 372 373 374 |
# File 'lib/sass/plugin/compiler.rb', line 362
def clean(individual_files = [])
file_list(individual_files).each do |(_, css_file, sourcemap_file)|
if File.exist?(css_file)
run_deleting_css css_file
File.delete(css_file)
end
if sourcemap_file && File.exist?(sourcemap_file)
run_deleting_sourcemap sourcemap_file
File.delete(sourcemap_file)
end
end
nil
end
|
#engine_options(additional_options = {}) ⇒ {Symbol => Object}
Non-destructively modifies Sass::Plugin::Configuration#options so that default values are properly set, and returns the result.
337 338 339 340 341 342 343 |
# File 'lib/sass/plugin/compiler.rb', line 337
def engine_options(additional_options = {})
opts = options.merge(additional_options)
opts[:load_paths] = load_paths(opts)
options[:sourcemap] = :auto if options[:sourcemap] == true
options[:sourcemap] = :none if options[:sourcemap] == false
opts
end
|
#file_list(individual_files = []) ⇒ Array<(String, String, String)>
Construct a list of files that might need to be compiled from the provided individual_files and the template_locations.
Note: this method does not cache the results as they can change across invocations when sass files are added or removed.
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/sass/plugin/compiler.rb', line 240
def file_list(individual_files = [])
files = individual_files.map do |tuple|
if engine_options[:sourcemap] == :none
tuple[0..1]
elsif tuple.size < 3
[tuple[0], tuple[1], Sass::Util.sourcemap_name(tuple[1])]
else
tuple.dup
end
end
template_location_array.each do |template_location, css_location|
Sass::Util.glob(File.join(template_location, "**", "[^_]*.s[ca]ss")).sort.each do |file|
# Get the relative path to the file
name = Sass::Util.relative_path_from(file, template_location).to_s
css = css_filename(name, css_location)
sourcemap = Sass::Util.sourcemap_name(css) unless engine_options[:sourcemap] == :none
files << [file, css, sourcemap]
end
end
files
end
|
#stylesheet_needs_update?(css_file, template_file) ⇒ Boolean
Compass expects this to exist
346 347 348 |
# File 'lib/sass/plugin/compiler.rb', line 346
def stylesheet_needs_update?(css_file, template_file)
StalenessChecker.stylesheet_needs_update?(css_file, template_file)
end
|
#update_stylesheets(individual_files = [])
Updates out-of-date stylesheets.
Checks each Sass/SCSS file in
:template_location
to see if it's been modified more recently than the corresponding CSS file
in :css_location
.
If it has, it updates the CSS file.
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/sass/plugin/compiler.rb', line 201
def update_stylesheets(individual_files = [])
Sass::Plugin.checked_for_updates = true
staleness_checker = StalenessChecker.new(engine_options)
files = file_list(individual_files)
run_updating_stylesheets(files)
updated_stylesheets = []
files.each do |file, css, sourcemap|
# TODO: Does staleness_checker need to check the sourcemap file as well?
if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
# XXX For consistency, this should return the sourcemap too, but it would
# XXX be an API change.
updated_stylesheets << [file, css]
update_stylesheet(file, css, sourcemap)
else
run_not_updating_stylesheet(file, css, sourcemap)
end
end
run_updated_stylesheets(updated_stylesheets)
end
|
#watch(individual_files = [], options = {})
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
:template_location
,
the corresponding CSS file in :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 Listen library
to monitor the filesystem for changes.
Listen isn't loaded until watch
is run.
The version of Listen distributed with Sass is loaded by default,
but if another version has already been loaded that will be used instead.
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/sass/plugin/compiler.rb', line 291
def watch(individual_files = [], options = {})
@inferred_directories = []
options, individual_files = individual_files, [] if individual_files.is_a?(Hash)
update_stylesheets(individual_files) unless options[:skip_initial_update]
directories = watched_paths
individual_files.each do |(source, _, _)|
source = File.expand_path(source)
@watched_files << Sass::Util.realpath(source).to_s
@inferred_directories << File.dirname(source)
end
directories += @inferred_directories
directories = remove_redundant_directories(directories)
# TODO: Keep better track of what depends on what
# so we don't have to run a global update every time anything changes.
# XXX The :additional_watch_paths option exists for Compass to use until
# a deprecated feature is removed. It may be removed without warning.
directories += Array(options[:additional_watch_paths])
options = {
:relative_paths => false,
# The native windows listener is much slower than the polling option, according to
# https://github.com/nex3/sass/commit/a3031856b22bc834a5417dedecb038b7be9b9e3e
:force_polling => @options[:poll] || Sass::Util.windows?
}
listener = create_listener(*directories, options) do |modified, added, removed|
on_file_changed(individual_files, modified, added, removed)
yield(modified, added, removed) if block_given?
end
begin
listener.start
sleep
rescue Interrupt
# Squelch Interrupt for clean exit from Listen::Listener
end
end
|