File: sass_compiler.rb

package info (click to toggle)
ruby-compass 1.0.1~dfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 8,152 kB
  • ctags: 1,795
  • sloc: ruby: 12,901; makefile: 127; perl: 43; xml: 14; sh: 4
file content (151 lines) | stat: -rw-r--r-- 4,645 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
require 'sass/plugin'

class Compass::SassCompiler

  include Compass::Actions

  attr_writer :logger
  attr_reader :quiet
  attr_reader :error_count
  attr_accessor :config
  attr_accessor :display_compilation_times
  attr_accessor :working_path
  attr_accessor :only_sass_files

  def initialize(options = {}, config = Compass.configuration)
    options = options.dup
    self.config = config
    self.display_compilation_times = options.delete(:time)
    self.working_path = options.delete(:working_path) || Dir.pwd
    self.only_sass_files = options.delete(:only_sass_files) || []
    @quiet = options[:quiet]
    plugin_options = config.to_sass_plugin_options.merge(options)
    if only_sass_files.any?
      plugin_options[:template_location] = []
      plugin_options[:load_paths] = config.sass_load_paths
    end
    plugin_options[:always_update] = true if options.delete(:force)
    plugin_options[:compass] ||= {}
    plugin_options[:compass][:logger] = logger
    @compiler = Sass::Plugin::Compiler.new(plugin_options)
    @start_times = {}
    @error_count = 0

    public_methods(true).grep(/^when_/).each do |callback|
      @compiler.send(callback.to_s.sub(/^when_/, 'on_')) {|*args| send(callback, *args) }
    end
  end

  def compile!
    @compiler.update_stylesheets(individual_files)
  end

  def watch!(options = {}, &block)
    skip_initial_update = options.fetch(:skip_initial_update, false)
    begin
      @compiler.watch(individual_files, options.merge(:skip_initial_update => skip_initial_update), &block)
    rescue Sass::SyntaxError => e
      skip_initial_update = true
      retry
    end
  end

  def individual_files
    only_sass_files.map {|sass_file| [sass_file, corresponding_css_file(sass_file)]}
  end

  def clean!
    @compiler.clean(individual_files)
  end

  def file_list
    @compiler.file_list(individual_files)
  end

  def when_updating_stylesheets(individual_files)
    @start_times = {}
    @error_count = 0
  end

  def when_compilation_starting(sass_file, css, sourcemap)
    @start_times[sass_file] = Time.now
  end

  def when_template_created(sass_file)
    logger.record :created, relativize(sass_file)
  end

  def when_template_deleted(sass_file)
    logger.record :deleted, relativize(sass_file)
  end

  def when_template_modified(sass_file)
    logger.record :modified, relativize(sass_file)
  end

  def when_updated_stylesheet(sass_file, css, sourcemap)
    if css && display_compilation_times && @start_times[sass_file]
      duration = ((Time.now - @start_times[sass_file]) * 1000).round / 1000.0
      logger.record :write, "#{relativize(css)} (#{duration}s)"
    else
      logger.record :write, relativize(css) if css
    end
    config.run_stylesheet_saved(css) if css

    logger.record :write, relativize(sourcemap) if sourcemap
    config.run_sourcemap_saved(sourcemap) if sourcemap
  end

  def when_creating_directory(dirname)
    logger.record :directory, relativize(dirname)
  end

  def when_deleting_css(filename)
    logger.record :delete, relativize(filename)
    config.run_stylesheet_removed(filename) if filename
  end

  def when_deleting_sourcemap(filename)
    logger.record :delete, relativize(filename)
    config.run_sourcemap_removed(filename) if filename
  end

  def when_compilation_error(error, sass_file, css_file, sourcemap_file)
    @error_count += 1
    if error.respond_to?(:sass_filename)
      if relativize(error.sass_filename) == relativize(sass_file)
        logger.record :error, "#{relativize(error.sass_filename)} (Line #{error.sass_line}: #{error.message})"
      else
        logger.record :error, "#{relativize(sass_file)} (Line #{error.sass_line} of #{relativize(error.sass_filename)}: #{error.message})"
      end
    else
      logger.record :error, "#{relativize(sass_file)} (#{error.backtrace.first}: #{error.message})"
    end
    config.run_stylesheet_error(sass_file, error.message)
  end

  def logger
    @logger ||= Compass::Logger.new(:quiet => quiet)
  end

  def corresponding_css_file(sass_file)
    "#{config.css_path}/#{stylesheet_name(sass_file)}.css"
  end

  def stylesheet_name(sass_file)
    if sass_file.index(config.sass_path) == 0
      sass_file[(config.sass_path.length + 1)..-6].sub(/\.css$/,'')
    else
      raise Compass::Error, "Individual stylesheets must be in the sass directory."
    end
  end

  def sass_files(options = {})
    @compiler.template_location_array.map do |(sass_dir, css_dir)|
      glob = options[:include_partials] ?
               File.join("**","*.s[ac]ss*") :
               File.join("**","[^_]*.s[ac]ss*")
      Dir.glob(File.join(sass_dir, glob))
    end.flatten
  end
end