Class: Guard::Sass

Inherits:
Plugin
  • Object
show all
Defined in:
lib/guard/sass.rb,
lib/guard/sass/runner.rb,
lib/guard/sass/importer.rb,
lib/guard/sass/formatter.rb

Defined Under Namespace

Classes: Formatter, Importer, Runner

Constant Summary collapse

DEFAULTS =
{
  :all_on_start => false,
  :output       => 'css',
  :extension    => '.css',
  :style        => :nested,
  :shallow      => false,
  :line_numbers => false,
  :debug_info   => false,
  :noop         => false,
  :hide_success => false,
  :load_paths   => ::Sass::Plugin.template_location_array.map(&:first)
}

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Sass

Returns a new instance of Sass.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :input (String)

    The input directory

  • :output (String)

    The output directory

  • :extension (String)

    The extension to replace the '.sss' part of the file name with

  • :load_paths (Array<String>)

    List of directories you can @import from

  • :shallow (Boolean)

    Whether to output nested directories

  • :line_numbers (Boolean)

    Whether to output human readable line numbers as comments in the file

  • :debug_info (Boolean)

    Whether to output file and line number info for FireSass

  • :noop (Boolean)

    Whether to run in “asset pipe” mode, no ouput, just validation

  • :hide_success (Boolean)

    Whether to hide all success messages

  • :style (Symbol)

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/guard/sass.rb', line 45

def initialize(options={})
  load_paths = options.delete(:load_paths) || []

  if options[:input]
    load_paths << options[:input]
    options[:output] = options[:input] unless options.has_key?(:output)
    options[:watchers] << ::Guard::Watcher.new(%r{^#{ options[:input] }/(.+\.s[ac]ss)$})
  end
  options = DEFAULTS.merge(options)

  if compass = options.delete(:compass)
    require 'compass'
    compass = {} unless compass.is_a?(Hash)

    Compass.configuration.project_path   ||= Dir.pwd

    compass.each do |key, value|
      Compass.configuration.send("#{key}=".to_sym, value)

      if key.to_s.include?('dir') && !key.to_s.include?('http')
        options[:load_paths] << value
      end
    end

    Compass.configuration.asset_cache_buster = Proc.new {|*| {:query => Time.now.to_i} }
    options[:load_paths] ||= []
    options[:load_paths] << Compass.configuration.sass_load_paths
  end

  options[:load_paths] += load_paths
  options[:load_paths].flatten!

  @formatter = Formatter.new(:hide_success => options[:hide_success])
  @runner = Runner.new(options[:watchers], @formatter, options)
  super(options)
end

Instance Method Details

#filesArray<String>

Returns Paths of all sass/scss files.

Returns:

  • (Array<String>)

    Paths of all sass/scss files


83
84
85
# File 'lib/guard/sass.rb', line 83

def files
  Watcher.match_files self, Dir['**/*.s[ac]ss']
end

#partial?(path) ⇒ Boolean

Returns Whether path is a partial.

Returns:

  • (Boolean)

    Whether path is a partial


163
164
165
# File 'lib/guard/sass.rb', line 163

def partial?(path)
  File.basename(path).start_with? '_'
end

#resolve_partials_to_owners(paths) ⇒ Object


101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/guard/sass.rb', line 101

def resolve_partials_to_owners(paths)
  # Get all files that might have imports
  search_files = Dir.glob("#{options[:input]}/**/*.s[ac]ss")
  search_files = Watcher.match_files(self, search_files)

  # Get owners
  owners = search_files.select do |file|
    deps = []
     begin
       # Get dependencies of file
       deps = ::Sass::Engine.for_file(file, @options).dependencies.collect! {|dep| dep.options[:filename] }

     rescue ::Sass::SyntaxError => e
       message = "Resolving partial owners of #{file} failed"
       @formatter.error "Sass > #{e.sass_backtrace_str(file)}", :notification => message
     end

     # Find intersection with paths
     deps_in_paths = deps.intersection paths
     # Any paths in the dependencies?
     !deps_in_paths.empty?
  end

  # Return our resolved set of paths to recompile
  owners
end

#run_allObject

Build all files being watched

Raises:

  • (:task_has_failed)

97
98
99
# File 'lib/guard/sass.rb', line 97

def run_all
  run_on_changes files.reject {|f| partial?(f) }
end

#run_on_changes(paths) ⇒ Object

Builds the files given. If a 'partial' file is found (name begins with '_'), calls #run_with_partials so that files which include it are rebuilt.

Fires a `:run_on_changes_end` hook with a `changed_files` array and a `success` bool as parameters.

Parameters:

  • paths (Array<String>)

Raises:

  • (:task_has_failed)

146
147
148
149
150
151
152
153
154
# File 'lib/guard/sass.rb', line 146

def run_on_changes(paths)
  return run_with_partials(paths) if paths.any? {|f| partial?(f) }

  changed_files, success = @runner.run(paths)

  hook :end, Array(changed_files), success

  throw :task_has_failed unless success
end

#run_on_removals(paths) ⇒ Object

Restore previous behaviour, when a file is removed we don't want to call #run_on_changes.


158
159
160
# File 'lib/guard/sass.rb', line 158

def run_on_removals(paths)

end

#run_with_partials(paths) ⇒ Object


128
129
130
131
132
133
134
135
# File 'lib/guard/sass.rb', line 128

def run_with_partials(paths)
  if options[:smart_partials]
    paths = resolve_partials_to_owners(paths)
    run_on_changes Watcher.match_files(self, paths) unless paths.nil?
  else
    run_all
  end
end

#startObject

If option set to run all on start, run all when started.

Raises:

  • (:task_has_failed)

90
91
92
# File 'lib/guard/sass.rb', line 90

def start
  run_all if options[:all_on_start]
end