sass 3.3.0 → 3.4.25
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +3 -1
- data/CODE_OF_CONDUCT.md +10 -0
- data/CONTRIBUTING.md +148 -0
- data/MIT-LICENSE +1 -1
- data/README.md +76 -62
- data/Rakefile +104 -24
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/VERSION_NAME +1 -1
- data/bin/sass +1 -1
- data/bin/scss +1 -1
- data/extra/sass-spec-ref.sh +32 -0
- data/extra/update_watch.rb +1 -1
- data/lib/sass/cache_stores/filesystem.rb +9 -5
- data/lib/sass/cache_stores/memory.rb +4 -5
- data/lib/sass/callbacks.rb +2 -2
- data/lib/sass/css.rb +12 -13
- data/lib/sass/deprecation.rb +55 -0
- data/lib/sass/engine.rb +106 -70
- data/lib/sass/environment.rb +39 -19
- data/lib/sass/error.rb +17 -20
- data/lib/sass/exec/base.rb +199 -0
- data/lib/sass/exec/sass_convert.rb +283 -0
- data/lib/sass/exec/sass_scss.rb +440 -0
- data/lib/sass/exec.rb +5 -771
- data/lib/sass/features.rb +9 -2
- data/lib/sass/importers/base.rb +8 -3
- data/lib/sass/importers/filesystem.rb +30 -38
- data/lib/sass/logger/base.rb +8 -2
- data/lib/sass/logger/delayed.rb +50 -0
- data/lib/sass/logger.rb +8 -3
- data/lib/sass/media.rb +1 -4
- data/lib/sass/plugin/compiler.rb +224 -90
- data/lib/sass/plugin/configuration.rb +38 -22
- data/lib/sass/plugin/merb.rb +2 -2
- data/lib/sass/plugin/rack.rb +3 -3
- data/lib/sass/plugin/rails.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +4 -4
- data/lib/sass/plugin.rb +6 -5
- data/lib/sass/script/css_lexer.rb +1 -1
- data/lib/sass/script/css_parser.rb +2 -3
- data/lib/sass/script/css_variable_warning.rb +52 -0
- data/lib/sass/script/functions.rb +739 -318
- data/lib/sass/script/lexer.rb +134 -54
- data/lib/sass/script/parser.rb +252 -56
- data/lib/sass/script/tree/funcall.rb +13 -6
- data/lib/sass/script/tree/interpolation.rb +127 -4
- data/lib/sass/script/tree/list_literal.rb +31 -4
- data/lib/sass/script/tree/literal.rb +4 -0
- data/lib/sass/script/tree/node.rb +21 -3
- data/lib/sass/script/tree/operation.rb +54 -1
- data/lib/sass/script/tree/selector.rb +26 -0
- data/lib/sass/script/tree/string_interpolation.rb +59 -38
- data/lib/sass/script/tree/variable.rb +1 -1
- data/lib/sass/script/tree.rb +1 -0
- data/lib/sass/script/value/base.rb +17 -14
- data/lib/sass/script/value/bool.rb +0 -5
- data/lib/sass/script/value/color.rb +78 -42
- data/lib/sass/script/value/helpers.rb +119 -2
- data/lib/sass/script/value/list.rb +0 -15
- data/lib/sass/script/value/map.rb +1 -1
- data/lib/sass/script/value/null.rb +0 -5
- data/lib/sass/script/value/number.rb +112 -31
- data/lib/sass/script/value/string.rb +102 -13
- data/lib/sass/script/value.rb +0 -1
- data/lib/sass/script.rb +3 -3
- data/lib/sass/scss/css_parser.rb +24 -4
- data/lib/sass/scss/parser.rb +290 -383
- data/lib/sass/scss/rx.rb +17 -9
- data/lib/sass/scss/static_parser.rb +306 -4
- data/lib/sass/scss.rb +0 -2
- data/lib/sass/selector/abstract_sequence.rb +35 -18
- data/lib/sass/selector/comma_sequence.rb +114 -19
- data/lib/sass/selector/pseudo.rb +266 -0
- data/lib/sass/selector/sequence.rb +146 -40
- data/lib/sass/selector/simple.rb +22 -33
- data/lib/sass/selector/simple_sequence.rb +122 -39
- data/lib/sass/selector.rb +57 -197
- data/lib/sass/shared.rb +2 -2
- data/lib/sass/source/map.rb +31 -14
- data/lib/sass/source/position.rb +4 -4
- data/lib/sass/stack.rb +2 -8
- data/lib/sass/supports.rb +10 -13
- data/lib/sass/tree/at_root_node.rb +1 -0
- data/lib/sass/tree/charset_node.rb +1 -1
- data/lib/sass/tree/comment_node.rb +1 -1
- data/lib/sass/tree/css_import_node.rb +9 -1
- data/lib/sass/tree/directive_node.rb +8 -2
- data/lib/sass/tree/error_node.rb +18 -0
- data/lib/sass/tree/extend_node.rb +1 -1
- data/lib/sass/tree/function_node.rb +9 -0
- data/lib/sass/tree/import_node.rb +6 -5
- data/lib/sass/tree/keyframe_rule_node.rb +15 -0
- data/lib/sass/tree/node.rb +5 -3
- data/lib/sass/tree/prop_node.rb +6 -7
- data/lib/sass/tree/rule_node.rb +26 -11
- data/lib/sass/tree/visitors/check_nesting.rb +56 -32
- data/lib/sass/tree/visitors/convert.rb +59 -44
- data/lib/sass/tree/visitors/cssize.rb +34 -30
- data/lib/sass/tree/visitors/deep_copy.rb +6 -1
- data/lib/sass/tree/visitors/extend.rb +15 -13
- data/lib/sass/tree/visitors/perform.rb +87 -50
- data/lib/sass/tree/visitors/set_options.rb +15 -1
- data/lib/sass/tree/visitors/to_css.rb +72 -43
- data/lib/sass/util/multibyte_string_scanner.rb +0 -2
- data/lib/sass/util/normalized_map.rb +0 -1
- data/lib/sass/util/subset_map.rb +2 -3
- data/lib/sass/util.rb +334 -154
- data/lib/sass/version.rb +7 -7
- data/lib/sass.rb +10 -8
- data/test/sass/cache_test.rb +62 -20
- data/test/sass/callbacks_test.rb +1 -1
- data/test/sass/compiler_test.rb +24 -11
- data/test/sass/conversion_test.rb +241 -50
- data/test/sass/css2sass_test.rb +73 -5
- data/test/sass/css_variable_test.rb +132 -0
- data/test/sass/encoding_test.rb +219 -0
- data/test/sass/engine_test.rb +343 -260
- data/test/sass/exec_test.rb +12 -2
- data/test/sass/extend_test.rb +333 -44
- data/test/sass/functions_test.rb +353 -260
- data/test/sass/importer_test.rb +40 -21
- data/test/sass/logger_test.rb +1 -1
- data/test/sass/more_results/more_import.css +1 -1
- data/test/sass/more_templates/more1.sass +10 -10
- data/test/sass/more_templates/more_import.sass +2 -2
- data/test/sass/plugin_test.rb +24 -21
- data/test/sass/results/compact.css +1 -1
- data/test/sass/results/complex.css +4 -4
- data/test/sass/results/expanded.css +1 -1
- data/test/sass/results/import.css +1 -1
- data/test/sass/results/import_charset_ibm866.css +2 -2
- data/test/sass/results/mixins.css +17 -17
- data/test/sass/results/nested.css +1 -1
- data/test/sass/results/parent_ref.css +2 -2
- data/test/sass/results/script.css +5 -5
- data/test/sass/results/scss_import.css +1 -1
- data/test/sass/script_conversion_test.rb +71 -39
- data/test/sass/script_test.rb +714 -123
- data/test/sass/scss/css_test.rb +213 -30
- data/test/sass/scss/rx_test.rb +8 -4
- data/test/sass/scss/scss_test.rb +766 -22
- data/test/sass/source_map_test.rb +263 -95
- data/test/sass/superselector_test.rb +210 -0
- data/test/sass/templates/_partial.sass +1 -1
- data/test/sass/templates/basic.sass +10 -10
- data/test/sass/templates/bork1.sass +1 -1
- data/test/sass/templates/bork5.sass +1 -1
- data/test/sass/templates/compact.sass +10 -10
- data/test/sass/templates/complex.sass +187 -187
- data/test/sass/templates/compressed.sass +10 -10
- data/test/sass/templates/expanded.sass +10 -10
- data/test/sass/templates/import.sass +2 -2
- data/test/sass/templates/importee.sass +3 -3
- data/test/sass/templates/mixins.sass +22 -22
- data/test/sass/templates/multiline.sass +4 -4
- data/test/sass/templates/nested.sass +13 -13
- data/test/sass/templates/parent_ref.sass +12 -12
- data/test/sass/templates/script.sass +70 -70
- data/test/sass/templates/scss_import.scss +2 -1
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +1 -1
- data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +2 -2
- data/test/sass/templates/subdir/subdir.sass +3 -3
- data/test/sass/templates/units.sass +10 -10
- data/test/sass/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +11 -3
- data/test/sass/util/normalized_map_test.rb +1 -1
- data/test/sass/util/subset_map_test.rb +2 -2
- data/test/sass/util_test.rb +46 -45
- data/test/sass/value_helpers_test.rb +5 -7
- data/test/sass-spec.yml +3 -0
- data/test/test_helper.rb +7 -6
- data/vendor/listen/CHANGELOG.md +1 -228
- data/vendor/listen/Gemfile +5 -15
- data/vendor/listen/README.md +111 -77
- data/vendor/listen/Rakefile +0 -42
- data/vendor/listen/lib/listen/adapter.rb +195 -82
- data/vendor/listen/lib/listen/adapters/bsd.rb +27 -64
- data/vendor/listen/lib/listen/adapters/darwin.rb +21 -58
- data/vendor/listen/lib/listen/adapters/linux.rb +23 -55
- data/vendor/listen/lib/listen/adapters/polling.rb +25 -34
- data/vendor/listen/lib/listen/adapters/windows.rb +50 -46
- data/vendor/listen/lib/listen/directory_record.rb +96 -61
- data/vendor/listen/lib/listen/listener.rb +135 -37
- data/vendor/listen/lib/listen/turnstile.rb +9 -5
- data/vendor/listen/lib/listen/version.rb +1 -1
- data/vendor/listen/lib/listen.rb +33 -19
- data/vendor/listen/listen.gemspec +6 -0
- data/vendor/listen/spec/listen/adapter_spec.rb +43 -77
- data/vendor/listen/spec/listen/adapters/polling_spec.rb +8 -8
- data/vendor/listen/spec/listen/directory_record_spec.rb +81 -56
- data/vendor/listen/spec/listen/listener_spec.rb +128 -39
- data/vendor/listen/spec/listen_spec.rb +15 -21
- data/vendor/listen/spec/spec_helper.rb +4 -0
- data/vendor/listen/spec/support/adapter_helper.rb +52 -15
- data/vendor/listen/spec/support/directory_record_helper.rb +7 -5
- data/vendor/listen/spec/support/listeners_helper.rb +30 -7
- metadata +310 -300
- data/CONTRIBUTING +0 -3
- data/ext/mkrf_conf.rb +0 -27
- data/lib/sass/script/value/deprecated_false.rb +0 -55
- data/lib/sass/scss/script_lexer.rb +0 -15
- data/lib/sass/scss/script_parser.rb +0 -25
- data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
- data/vendor/listen/lib/listen/multi_listener.rb +0 -143
- data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
- data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
data/lib/sass/plugin/compiler.rb
CHANGED
@@ -31,24 +31,36 @@ module Sass::Plugin
|
|
31
31
|
# Creates a new compiler.
|
32
32
|
#
|
33
33
|
# @param opts [{Symbol => Object}]
|
34
|
-
# See {file:SASS_REFERENCE.md#
|
34
|
+
# See {file:SASS_REFERENCE.md#Options the Sass options documentation}.
|
35
35
|
def initialize(opts = {})
|
36
|
+
@watched_files = Set.new
|
36
37
|
options.merge!(opts)
|
37
38
|
end
|
38
39
|
|
39
|
-
# Register a callback to be run
|
40
|
+
# Register a callback to be run before stylesheets are mass-updated.
|
40
41
|
# This is run whenever \{#update\_stylesheets} is called,
|
41
42
|
# unless the \{file:SASS_REFERENCE.md#never_update-option `:never_update` option}
|
42
43
|
# is enabled.
|
43
44
|
#
|
44
|
-
# @yield [
|
45
|
-
# @yieldparam
|
46
|
-
# Individual files to be updated
|
47
|
-
# specified in the options.
|
45
|
+
# @yield [files]
|
46
|
+
# @yieldparam files [<(String, String, String)>]
|
47
|
+
# Individual files to be updated. Files in directories specified are included in this list.
|
48
48
|
# The first element of each pair is the source file,
|
49
|
-
# the second is the target CSS file
|
49
|
+
# the second is the target CSS file,
|
50
|
+
# the third is the target sourcemap file.
|
50
51
|
define_callback :updating_stylesheets
|
51
52
|
|
53
|
+
# Register a callback to be run after stylesheets are mass-updated.
|
54
|
+
# This is run whenever \{#update\_stylesheets} is called,
|
55
|
+
# unless the \{file:SASS_REFERENCE.md#never_update-option `:never_update` option}
|
56
|
+
# is enabled.
|
57
|
+
#
|
58
|
+
# @yield [updated_files]
|
59
|
+
# @yieldparam updated_files [<(String, String)>]
|
60
|
+
# Individual files that were updated.
|
61
|
+
# The first element of each pair is the source file, the second is the target CSS file.
|
62
|
+
define_callback :updated_stylesheets
|
63
|
+
|
52
64
|
# Register a callback to be run after a single stylesheet is updated.
|
53
65
|
# The callback is only run if the stylesheet is really updated;
|
54
66
|
# if the CSS file is fresh, this won't be run.
|
@@ -67,6 +79,21 @@ module Sass::Plugin
|
|
67
79
|
# The location of the sourcemap being generated, if any.
|
68
80
|
define_callback :updated_stylesheet
|
69
81
|
|
82
|
+
# Register a callback to be run when compilation starts.
|
83
|
+
#
|
84
|
+
# In combination with on_updated_stylesheet, this could be used
|
85
|
+
# to collect compilation statistics like timing or to take a
|
86
|
+
# diff of the changes to the output file.
|
87
|
+
#
|
88
|
+
# @yield [template, css, sourcemap]
|
89
|
+
# @yieldparam template [String]
|
90
|
+
# The location of the Sass/SCSS file being updated.
|
91
|
+
# @yieldparam css [String]
|
92
|
+
# The location of the CSS file being generated.
|
93
|
+
# @yieldparam sourcemap [String]
|
94
|
+
# The location of the sourcemap being generated, if any.
|
95
|
+
define_callback :compilation_starting
|
96
|
+
|
70
97
|
# Register a callback to be run when Sass decides not to update a stylesheet.
|
71
98
|
# In particular, the callback is run when Sass finds that
|
72
99
|
# the template file and none of its dependencies
|
@@ -139,7 +166,8 @@ module Sass::Plugin
|
|
139
166
|
define_callback :template_deleted
|
140
167
|
|
141
168
|
# Register a callback to be run when Sass deletes a CSS file.
|
142
|
-
# This happens when the corresponding Sass/SCSS file has been deleted
|
169
|
+
# This happens when the corresponding Sass/SCSS file has been deleted
|
170
|
+
# and when the compiler cleans the output files.
|
143
171
|
#
|
144
172
|
# @yield [filename]
|
145
173
|
# @yieldparam filename [String]
|
@@ -147,7 +175,8 @@ module Sass::Plugin
|
|
147
175
|
define_callback :deleting_css
|
148
176
|
|
149
177
|
# Register a callback to be run when Sass deletes a sourcemap file.
|
150
|
-
# This happens when the corresponding Sass/SCSS file has been deleted
|
178
|
+
# This happens when the corresponding Sass/SCSS file has been deleted
|
179
|
+
# and when the compiler cleans the output files.
|
151
180
|
#
|
152
181
|
# @yield [filename]
|
153
182
|
# @yieldparam filename [String]
|
@@ -162,35 +191,73 @@ module Sass::Plugin
|
|
162
191
|
# in {file:SASS_REFERENCE.md#css_location-option `:css_location`}.
|
163
192
|
# If it has, it updates the CSS file.
|
164
193
|
#
|
165
|
-
# @param individual_files [Array<(String, String)>]
|
194
|
+
# @param individual_files [Array<(String, String[, String])>]
|
166
195
|
# A list of files to check for updates
|
167
196
|
# **in addition to those specified by the
|
168
197
|
# {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
|
169
198
|
# The first string in each pair is the location of the Sass/SCSS file,
|
170
199
|
# the second is the location of the CSS file that it should be compiled to.
|
200
|
+
# The third string, if provided, is the location of the Sourcemap file.
|
171
201
|
def update_stylesheets(individual_files = [])
|
172
|
-
individual_files = individual_files.dup
|
173
202
|
Sass::Plugin.checked_for_updates = true
|
174
203
|
staleness_checker = StalenessChecker.new(engine_options)
|
175
204
|
|
176
|
-
|
177
|
-
|
178
|
-
# Get the relative path to the file
|
179
|
-
name = file.sub(template_location.to_s.sub(/\/*$/, '/'), "")
|
180
|
-
css = css_filename(name, css_location)
|
181
|
-
sourcemap = Sass::Util.sourcemap_name(css) if engine_options[:sourcemap]
|
182
|
-
individual_files << [file, css, sourcemap]
|
183
|
-
end
|
184
|
-
end
|
205
|
+
files = file_list(individual_files)
|
206
|
+
run_updating_stylesheets(files)
|
185
207
|
|
186
|
-
|
208
|
+
updated_stylesheets = []
|
209
|
+
files.each do |file, css, sourcemap|
|
187
210
|
# TODO: Does staleness_checker need to check the sourcemap file as well?
|
188
211
|
if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
|
212
|
+
# XXX For consistency, this should return the sourcemap too, but it would
|
213
|
+
# XXX be an API change.
|
214
|
+
updated_stylesheets << [file, css]
|
189
215
|
update_stylesheet(file, css, sourcemap)
|
190
216
|
else
|
191
217
|
run_not_updating_stylesheet(file, css, sourcemap)
|
192
218
|
end
|
193
219
|
end
|
220
|
+
run_updated_stylesheets(updated_stylesheets)
|
221
|
+
end
|
222
|
+
|
223
|
+
# Construct a list of files that might need to be compiled
|
224
|
+
# from the provided individual_files and the template_locations.
|
225
|
+
#
|
226
|
+
# Note: this method does not cache the results as they can change
|
227
|
+
# across invocations when sass files are added or removed.
|
228
|
+
#
|
229
|
+
# @param individual_files [Array<(String, String[, String])>]
|
230
|
+
# A list of files to check for updates
|
231
|
+
# **in addition to those specified by the
|
232
|
+
# {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
|
233
|
+
# The first string in each pair is the location of the Sass/SCSS file,
|
234
|
+
# the second is the location of the CSS file that it should be compiled to.
|
235
|
+
# The third string, if provided, is the location of the Sourcemap file.
|
236
|
+
# @return [Array<(String, String, String)>]
|
237
|
+
# A list of [sass_file, css_file, sourcemap_file] tuples similar
|
238
|
+
# to what was passed in, but expanded to include the current state
|
239
|
+
# of the directories being updated.
|
240
|
+
def file_list(individual_files = [])
|
241
|
+
files = individual_files.map do |tuple|
|
242
|
+
if engine_options[:sourcemap] == :none
|
243
|
+
tuple[0..1]
|
244
|
+
elsif tuple.size < 3
|
245
|
+
[tuple[0], tuple[1], Sass::Util.sourcemap_name(tuple[1])]
|
246
|
+
else
|
247
|
+
tuple.dup
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
template_location_array.each do |template_location, css_location|
|
252
|
+
Sass::Util.glob(File.join(template_location, "**", "[^_]*.s[ca]ss")).sort.each do |file|
|
253
|
+
# Get the relative path to the file
|
254
|
+
name = Sass::Util.relative_path_from(file, template_location).to_s
|
255
|
+
css = css_filename(name, css_location)
|
256
|
+
sourcemap = Sass::Util.sourcemap_name(css) unless engine_options[:sourcemap] == :none
|
257
|
+
files << [file, css, sourcemap]
|
258
|
+
end
|
259
|
+
end
|
260
|
+
files
|
194
261
|
end
|
195
262
|
|
196
263
|
# Watches the template directory (or directories)
|
@@ -211,24 +278,45 @@ module Sass::Plugin
|
|
211
278
|
# The version of Listen distributed with Sass is loaded by default,
|
212
279
|
# but if another version has already been loaded that will be used instead.
|
213
280
|
#
|
214
|
-
# @param individual_files [Array<(String, String)>]
|
215
|
-
# A list of files to
|
281
|
+
# @param individual_files [Array<(String, String[, String])>]
|
282
|
+
# A list of files to check for updates
|
216
283
|
# **in addition to those specified by the
|
217
284
|
# {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
|
218
285
|
# The first string in each pair is the location of the Sass/SCSS file,
|
219
286
|
# the second is the location of the CSS file that it should be compiled to.
|
220
|
-
|
221
|
-
|
287
|
+
# The third string, if provided, is the location of the Sourcemap file.
|
288
|
+
# @param options [Hash] The options that control how watching works.
|
289
|
+
# @option options [Boolean] :skip_initial_update
|
290
|
+
# Don't do an initial update when starting the watcher when true
|
291
|
+
def watch(individual_files = [], options = {})
|
292
|
+
@inferred_directories = []
|
293
|
+
options, individual_files = individual_files, [] if individual_files.is_a?(Hash)
|
294
|
+
update_stylesheets(individual_files) unless options[:skip_initial_update]
|
222
295
|
|
223
296
|
directories = watched_paths
|
224
297
|
individual_files.each do |(source, _, _)|
|
225
|
-
|
298
|
+
source = File.expand_path(source)
|
299
|
+
@watched_files << Sass::Util.realpath(source).to_s
|
300
|
+
@inferred_directories << File.dirname(source)
|
226
301
|
end
|
302
|
+
|
303
|
+
directories += @inferred_directories
|
227
304
|
directories = remove_redundant_directories(directories)
|
228
305
|
|
306
|
+
# A Listen version prior to 2.0 will write a test file to a directory to
|
307
|
+
# see if a watcher supports watching that directory. That breaks horribly
|
308
|
+
# on read-only directories, so we filter those out.
|
309
|
+
unless Sass::Util.listen_geq_2?
|
310
|
+
directories = directories.select {|d| File.directory?(d) && File.writable?(d)}
|
311
|
+
end
|
312
|
+
|
229
313
|
# TODO: Keep better track of what depends on what
|
230
314
|
# so we don't have to run a global update every time anything changes.
|
231
|
-
|
315
|
+
# XXX The :additional_watch_paths option exists for Compass to use until
|
316
|
+
# a deprecated feature is removed. It may be removed without warning.
|
317
|
+
listener_args = directories +
|
318
|
+
Array(options[:additional_watch_paths]) +
|
319
|
+
[{:relative_paths => false}]
|
232
320
|
|
233
321
|
# The native windows listener is much slower than the polling option, according to
|
234
322
|
# https://github.com/nex3/sass/commit/a3031856b22bc834a5417dedecb038b7be9b9e3e
|
@@ -240,49 +328,8 @@ module Sass::Plugin
|
|
240
328
|
end
|
241
329
|
|
242
330
|
listener = create_listener(*listener_args) do |modified, added, removed|
|
243
|
-
|
244
|
-
|
245
|
-
modified.uniq.each do |f|
|
246
|
-
next unless watched_file?(f)
|
247
|
-
recompile_required = true
|
248
|
-
run_template_modified(relative_to_pwd(f))
|
249
|
-
end
|
250
|
-
|
251
|
-
added.uniq.each do |f|
|
252
|
-
next unless watched_file?(f)
|
253
|
-
recompile_required = true
|
254
|
-
run_template_created(relative_to_pwd(f))
|
255
|
-
end
|
256
|
-
|
257
|
-
removed.uniq.each do |f|
|
258
|
-
if (files = individual_files.find {|(source, _, _)| File.expand_path(source) == f})
|
259
|
-
recompile_required = true
|
260
|
-
# This was a file we were watching explicitly and compiling to a particular location.
|
261
|
-
# Delete the corresponding file.
|
262
|
-
try_delete_css files[1]
|
263
|
-
else
|
264
|
-
next unless watched_file?(f)
|
265
|
-
recompile_required = true
|
266
|
-
# Look for the sass directory that contained the sass file
|
267
|
-
# And try to remove the css file that corresponds to it
|
268
|
-
template_location_array.each do |(sass_dir, css_dir)|
|
269
|
-
sass_dir = File.expand_path(sass_dir)
|
270
|
-
if child_of_directory?(sass_dir, f)
|
271
|
-
remainder = f[(sass_dir.size + 1)..-1]
|
272
|
-
try_delete_css(css_filename(remainder, css_dir))
|
273
|
-
break
|
274
|
-
end
|
275
|
-
end
|
276
|
-
end
|
277
|
-
run_template_deleted(relative_to_pwd(f))
|
278
|
-
end
|
279
|
-
|
280
|
-
if recompile_required
|
281
|
-
# In case a file we're watching is removed and then recreated we
|
282
|
-
# prune out the non-existant files here.
|
283
|
-
watched_files_remaining = individual_files.select {|(source, _, _)| File.exists?(source)}
|
284
|
-
update_stylesheets(watched_files_remaining)
|
285
|
-
end
|
331
|
+
on_file_changed(individual_files, modified, added, removed)
|
332
|
+
yield(modified, added, removed) if block_given?
|
286
333
|
end
|
287
334
|
|
288
335
|
if poll && !Sass::Util.listen_geq_2?
|
@@ -302,6 +349,8 @@ module Sass::Plugin
|
|
302
349
|
def engine_options(additional_options = {})
|
303
350
|
opts = options.merge(additional_options)
|
304
351
|
opts[:load_paths] = load_paths(opts)
|
352
|
+
options[:sourcemap] = :auto if options[:sourcemap] == true
|
353
|
+
options[:sourcemap] = :none if options[:sourcemap] == false
|
305
354
|
opts
|
306
355
|
end
|
307
356
|
|
@@ -310,12 +359,42 @@ module Sass::Plugin
|
|
310
359
|
StalenessChecker.stylesheet_needs_update?(css_file, template_file)
|
311
360
|
end
|
312
361
|
|
362
|
+
# Remove all output files that would be created by calling update_stylesheets, if they exist.
|
363
|
+
#
|
364
|
+
# This method runs the deleting_css and deleting_sourcemap callbacks for
|
365
|
+
# the files that are deleted.
|
366
|
+
#
|
367
|
+
# @param individual_files [Array<(String, String[, String])>]
|
368
|
+
# A list of files to check for updates
|
369
|
+
# **in addition to those specified by the
|
370
|
+
# {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
|
371
|
+
# The first string in each pair is the location of the Sass/SCSS file,
|
372
|
+
# the second is the location of the CSS file that it should be compiled to.
|
373
|
+
# The third string, if provided, is the location of the Sourcemap file.
|
374
|
+
def clean(individual_files = [])
|
375
|
+
file_list(individual_files).each do |(_, css_file, sourcemap_file)|
|
376
|
+
if File.exist?(css_file)
|
377
|
+
run_deleting_css css_file
|
378
|
+
File.delete(css_file)
|
379
|
+
end
|
380
|
+
if sourcemap_file && File.exist?(sourcemap_file)
|
381
|
+
run_deleting_sourcemap sourcemap_file
|
382
|
+
File.delete(sourcemap_file)
|
383
|
+
end
|
384
|
+
end
|
385
|
+
nil
|
386
|
+
end
|
387
|
+
|
313
388
|
private
|
314
389
|
|
315
390
|
def create_listener(*args, &block)
|
316
|
-
|
391
|
+
Sass::Util.load_listen!
|
317
392
|
if Sass::Util.listen_geq_2?
|
318
|
-
|
393
|
+
# Work around guard/listen#243.
|
394
|
+
options = args.pop if args.last.is_a?(Hash)
|
395
|
+
args.map do |dir|
|
396
|
+
Listen.to(dir, options, &block)
|
397
|
+
end
|
319
398
|
else
|
320
399
|
Listen::Listener.new(*args, &block)
|
321
400
|
end
|
@@ -323,16 +402,13 @@ module Sass::Plugin
|
|
323
402
|
|
324
403
|
def listen_to(listener)
|
325
404
|
if Sass::Util.listen_geq_2?
|
326
|
-
listener.start
|
327
|
-
|
328
|
-
listener.stop # Partially work around guard/listen#146
|
405
|
+
listener.map {|l| l.start}
|
406
|
+
sleep
|
329
407
|
else
|
330
|
-
|
331
|
-
listener.start!
|
332
|
-
rescue Interrupt
|
333
|
-
# Squelch Interrupt for clean exit from Listen::Listener
|
334
|
-
end
|
408
|
+
listener.start!
|
335
409
|
end
|
410
|
+
rescue Interrupt
|
411
|
+
# Squelch Interrupt for clean exit from Listen::Listener
|
336
412
|
end
|
337
413
|
|
338
414
|
def remove_redundant_directories(directories)
|
@@ -351,9 +427,55 @@ module Sass::Plugin
|
|
351
427
|
dedupped
|
352
428
|
end
|
353
429
|
|
430
|
+
def on_file_changed(individual_files, modified, added, removed)
|
431
|
+
recompile_required = false
|
432
|
+
|
433
|
+
modified.uniq.each do |f|
|
434
|
+
next unless watched_file?(f)
|
435
|
+
recompile_required = true
|
436
|
+
run_template_modified(relative_to_pwd(f))
|
437
|
+
end
|
438
|
+
|
439
|
+
added.uniq.each do |f|
|
440
|
+
next unless watched_file?(f)
|
441
|
+
recompile_required = true
|
442
|
+
run_template_created(relative_to_pwd(f))
|
443
|
+
end
|
444
|
+
|
445
|
+
removed.uniq.each do |f|
|
446
|
+
next unless watched_file?(f)
|
447
|
+
run_template_deleted(relative_to_pwd(f))
|
448
|
+
if (files = individual_files.find {|(source, _, _)| File.expand_path(source) == f})
|
449
|
+
recompile_required = true
|
450
|
+
# This was a file we were watching explicitly and compiling to a particular location.
|
451
|
+
# Delete the corresponding file.
|
452
|
+
try_delete_css files[1]
|
453
|
+
else
|
454
|
+
next unless watched_file?(f)
|
455
|
+
recompile_required = true
|
456
|
+
# Look for the sass directory that contained the sass file
|
457
|
+
# And try to remove the css file that corresponds to it
|
458
|
+
template_location_array.each do |(sass_dir, css_dir)|
|
459
|
+
sass_dir = File.expand_path(sass_dir)
|
460
|
+
next unless child_of_directory?(sass_dir, f)
|
461
|
+
remainder = f[(sass_dir.size + 1)..-1]
|
462
|
+
try_delete_css(css_filename(remainder, css_dir))
|
463
|
+
break
|
464
|
+
end
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
return unless recompile_required
|
469
|
+
|
470
|
+
# In case a file we're watching is removed and then recreated we
|
471
|
+
# prune out the non-existant files here.
|
472
|
+
watched_files_remaining = individual_files.select {|(source, _, _)| File.exist?(source)}
|
473
|
+
update_stylesheets(watched_files_remaining)
|
474
|
+
end
|
475
|
+
|
354
476
|
def update_stylesheet(filename, css, sourcemap)
|
355
477
|
dir = File.dirname(css)
|
356
|
-
unless File.
|
478
|
+
unless File.exist?(dir)
|
357
479
|
run_creating_directory dir
|
358
480
|
FileUtils.mkdir_p dir
|
359
481
|
end
|
@@ -364,6 +486,7 @@ module Sass::Plugin
|
|
364
486
|
:filename => filename,
|
365
487
|
:sourcemap_filename => sourcemap)
|
366
488
|
mapping = nil
|
489
|
+
run_compilation_starting(filename, css, sourcemap)
|
367
490
|
engine = Sass::Engine.for_file(filename, engine_opts)
|
368
491
|
if sourcemap
|
369
492
|
rendered, mapping = engine.render_with_sourcemap(File.basename(sourcemap))
|
@@ -373,12 +496,16 @@ module Sass::Plugin
|
|
373
496
|
rescue StandardError => e
|
374
497
|
compilation_error_occured = true
|
375
498
|
run_compilation_error e, filename, css, sourcemap
|
376
|
-
|
499
|
+
raise e unless options[:full_exception]
|
500
|
+
rendered = Sass::SyntaxError.exception_to_css(e, options[:line] || 1)
|
377
501
|
end
|
378
502
|
|
379
503
|
write_file(css, rendered)
|
380
504
|
if mapping
|
381
|
-
write_file(
|
505
|
+
write_file(
|
506
|
+
sourcemap,
|
507
|
+
mapping.to_json(
|
508
|
+
:css_path => css, :sourcemap_path => sourcemap, :type => options[:sourcemap]))
|
382
509
|
end
|
383
510
|
run_updated_stylesheet(filename, css, sourcemap) unless compilation_error_occured
|
384
511
|
end
|
@@ -393,19 +520,26 @@ module Sass::Plugin
|
|
393
520
|
end
|
394
521
|
|
395
522
|
def try_delete_css(css)
|
396
|
-
if File.
|
523
|
+
if File.exist?(css)
|
397
524
|
run_deleting_css css
|
398
525
|
File.delete css
|
399
526
|
end
|
400
527
|
map = Sass::Util.sourcemap_name(css)
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
528
|
+
|
529
|
+
return unless File.exist?(map)
|
530
|
+
|
531
|
+
run_deleting_sourcemap map
|
532
|
+
File.delete map
|
405
533
|
end
|
406
534
|
|
407
535
|
def watched_file?(file)
|
408
|
-
|
536
|
+
@watched_files.include?(file) ||
|
537
|
+
normalized_load_paths.any? {|lp| lp.watched_file?(file)} ||
|
538
|
+
@inferred_directories.any? {|d| sass_file_in_directory?(d, file)}
|
539
|
+
end
|
540
|
+
|
541
|
+
def sass_file_in_directory?(directory, filename)
|
542
|
+
filename =~ /\.s[ac]ss$/ && filename.start_with?(directory + File::SEPARATOR)
|
409
543
|
end
|
410
544
|
|
411
545
|
def watched_paths
|
@@ -435,7 +569,7 @@ module Sass::Plugin
|
|
435
569
|
end
|
436
570
|
|
437
571
|
def relative_to_pwd(f)
|
438
|
-
Sass::Util.
|
572
|
+
Sass::Util.relative_path_from(f, Dir.pwd).to_s
|
439
573
|
rescue ArgumentError # when a relative path cannot be computed
|
440
574
|
f
|
441
575
|
end
|
@@ -1,8 +1,10 @@
|
|
1
1
|
module Sass
|
2
2
|
module Plugin
|
3
|
-
# We keep configuration in its own self-contained file
|
4
|
-
#
|
5
|
-
#
|
3
|
+
# We keep configuration in its own self-contained file so that we can load
|
4
|
+
# it independently in Rails 3, where the full plugin stuff is lazy-loaded.
|
5
|
+
#
|
6
|
+
# Note that this is not guaranteed to be thread-safe. For guaranteed thread
|
7
|
+
# safety, use a separate {Sass::Plugin} for each thread.
|
6
8
|
module Configuration
|
7
9
|
# Returns the default options for a {Sass::Plugin::Compiler}.
|
8
10
|
#
|
@@ -25,7 +27,7 @@ module Sass
|
|
25
27
|
end
|
26
28
|
|
27
29
|
# An options hash.
|
28
|
-
# See {file:SASS_REFERENCE.md#
|
30
|
+
# See {file:SASS_REFERENCE.md#Options the Sass options documentation}.
|
29
31
|
#
|
30
32
|
# @return [{Symbol => Object}]
|
31
33
|
def options
|
@@ -85,33 +87,47 @@ module Sass
|
|
85
87
|
# See the {file:SASS_REFERENCE.md#template_location-option `:template_location` option}
|
86
88
|
# for details.
|
87
89
|
#
|
90
|
+
# Modifications to the returned array may not be persistent. Use {#add_template_location}
|
91
|
+
# and {#remove_template_location} instead.
|
92
|
+
#
|
88
93
|
# @return [Array<(String, String)>]
|
89
94
|
# An array of `[template_location, css_location]` pairs.
|
90
95
|
def template_location_array
|
91
|
-
|
92
|
-
normalize_template_location!
|
93
|
-
options[:template_location]
|
94
|
-
ensure
|
95
|
-
options[:template_location] = old_template_location
|
96
|
+
convert_template_location(options[:template_location], options[:css_location])
|
96
97
|
end
|
97
98
|
|
98
99
|
private
|
99
100
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
101
|
+
# Returns the given template location, as an array. If it's already an array,
|
102
|
+
# it is returned unmodified. Otherwise, a new array is created and returned.
|
103
|
+
#
|
104
|
+
# @param template_location [String, Array<(String, String)>]
|
105
|
+
# A single template location, or a pre-normalized array of template
|
106
|
+
# locations and CSS locations.
|
107
|
+
# @param css_location [String?]
|
108
|
+
# The location for compiled CSS files.
|
109
|
+
# @return [Array<(String, String)>]
|
110
|
+
# An array of `[template_location, css_location]` pairs.
|
111
|
+
def convert_template_location(template_location, css_location)
|
112
|
+
return template_location if template_location.is_a?(Array)
|
113
|
+
|
114
|
+
case template_location
|
115
|
+
when nil
|
116
|
+
if css_location
|
117
|
+
[[File.join(css_location, 'sass'), css_location]]
|
112
118
|
else
|
113
|
-
|
119
|
+
[]
|
114
120
|
end
|
121
|
+
when String
|
122
|
+
[[template_location, css_location]]
|
123
|
+
else
|
124
|
+
template_location.to_a
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def normalize_template_location!
|
129
|
+
options[:template_location] = convert_template_location(
|
130
|
+
options[:template_location], options[:css_location])
|
115
131
|
end
|
116
132
|
end
|
117
133
|
end
|
data/lib/sass/plugin/merb.rb
CHANGED
@@ -2,7 +2,7 @@ unless defined?(Sass::MERB_LOADED)
|
|
2
2
|
Sass::MERB_LOADED = true
|
3
3
|
|
4
4
|
module Sass::Plugin::Configuration
|
5
|
-
# Different default options in a m
|
5
|
+
# Different default options in a m environment.
|
6
6
|
def default_options
|
7
7
|
@default_options ||= begin
|
8
8
|
version = Merb::VERSION.split('.').map {|n| n.to_i}
|
@@ -15,7 +15,7 @@ unless defined?(Sass::MERB_LOADED)
|
|
15
15
|
end
|
16
16
|
|
17
17
|
{
|
18
|
-
:always_update
|
18
|
+
:always_update => false,
|
19
19
|
:template_location => root + '/public/stylesheets/sass',
|
20
20
|
:css_location => root + '/public/stylesheets',
|
21
21
|
:cache_location => root + '/tmp/sass-cache',
|
data/lib/sass/plugin/rack.rb
CHANGED
@@ -9,19 +9,19 @@ module Sass
|
|
9
9
|
#
|
10
10
|
# ## Customize
|
11
11
|
#
|
12
|
-
# Sass::Plugin.options.merge(
|
12
|
+
# Sass::Plugin.options.merge!(
|
13
13
|
# :cache_location => './tmp/sass-cache',
|
14
14
|
# :never_update => environment != :production,
|
15
15
|
# :full_exception => environment != :production)
|
16
16
|
#
|
17
|
-
# {file:SASS_REFERENCE.md#
|
17
|
+
# {file:SASS_REFERENCE.md#Options See the Reference for more options}.
|
18
18
|
#
|
19
19
|
# ## Use
|
20
20
|
#
|
21
21
|
# Put your Sass files in `public/stylesheets/sass`.
|
22
22
|
# Your CSS will be generated in `public/stylesheets`,
|
23
23
|
# and regenerated every request if necessary.
|
24
|
-
# The locations and frequency {file:SASS_REFERENCE.md#
|
24
|
+
# The locations and frequency {file:SASS_REFERENCE.md#Options can be customized}.
|
25
25
|
# That's all there is to it!
|
26
26
|
class Rack
|
27
27
|
# The delay, in seconds, between update checks.
|
data/lib/sass/plugin/rails.rb
CHANGED
@@ -2,7 +2,7 @@ unless defined?(Sass::RAILS_LOADED)
|
|
2
2
|
Sass::RAILS_LOADED = true
|
3
3
|
|
4
4
|
module Sass::Plugin::Configuration
|
5
|
-
# Different default options in a rails
|
5
|
+
# Different default options in a rails environment.
|
6
6
|
def default_options
|
7
7
|
return @default_options if @default_options
|
8
8
|
opts = {
|
@@ -39,14 +39,14 @@ module Sass
|
|
39
39
|
# for checking the staleness of several stylesheets at once.
|
40
40
|
#
|
41
41
|
# @param options [{Symbol => Object}]
|
42
|
-
# See {file:SASS_REFERENCE.md#
|
42
|
+
# See {file:SASS_REFERENCE.md#Options the Sass options documentation}.
|
43
43
|
def initialize(options)
|
44
44
|
# URIs that are being actively checked for staleness. Protects against
|
45
45
|
# import loops.
|
46
46
|
@actively_checking = Set.new
|
47
47
|
|
48
48
|
# Entries in the following instance-level caches are never explicitly expired.
|
49
|
-
# Instead they are supposed to
|
49
|
+
# Instead they are supposed to automatically go out of scope when a series of staleness
|
50
50
|
# checks (this instance of StalenessChecker was created for) is finished.
|
51
51
|
@mtimes, @dependencies_stale, @parse_trees = {}, {}, {}
|
52
52
|
@options = Sass::Engine.normalize_options(options)
|
@@ -72,7 +72,7 @@ module Sass
|
|
72
72
|
# Returns whether a Sass or SCSS stylesheet has been modified since a given time.
|
73
73
|
#
|
74
74
|
# @param template_file [String] The location of the Sass or SCSS template.
|
75
|
-
# @param mtime [
|
75
|
+
# @param mtime [Time] The modification time to check against.
|
76
76
|
# @param importer [Sass::Importers::Base] The importer used to locate the stylesheet.
|
77
77
|
# Defaults to the filesystem importer.
|
78
78
|
# @return [Boolean] Whether the stylesheet has been modified.
|
@@ -103,7 +103,7 @@ module Sass
|
|
103
103
|
# so it's better to use when checking multiple stylesheets at once.
|
104
104
|
#
|
105
105
|
# @param template_file [String] The location of the Sass or SCSS template.
|
106
|
-
# @param mtime [
|
106
|
+
# @param mtime [Time] The modification time to check against.
|
107
107
|
# @param importer [Sass::Importers::Base] The importer used to locate the stylesheet.
|
108
108
|
# Defaults to the filesystem importer.
|
109
109
|
# @return [Boolean] Whether the stylesheet has been modified.
|
data/lib/sass/plugin.rb
CHANGED
@@ -12,7 +12,7 @@ module Sass
|
|
12
12
|
# when it's used as a plugin for various frameworks.
|
13
13
|
# All Rack-enabled frameworks are supported out of the box.
|
14
14
|
# The plugin is
|
15
|
-
# {file:SASS_REFERENCE.md#
|
15
|
+
# {file:SASS_REFERENCE.md#Rack_Rails_Merb_Plugin automatically activated for Rails and Merb}.
|
16
16
|
# Other frameworks must enable it explicitly; see {Sass::Plugin::Rack}.
|
17
17
|
#
|
18
18
|
# This module has a large set of callbacks available
|
@@ -93,7 +93,8 @@ module Sass
|
|
93
93
|
# the second is the location of the CSS file that it should be compiled to.
|
94
94
|
# @see #update_stylesheets
|
95
95
|
def force_update_stylesheets(individual_files = [])
|
96
|
-
Compiler.new(
|
96
|
+
Compiler.new(
|
97
|
+
options.dup.merge(
|
97
98
|
:never_update => false,
|
98
99
|
:always_update => true,
|
99
100
|
:cache => false)).update_stylesheets(individual_files)
|
@@ -123,9 +124,9 @@ module Sass
|
|
123
124
|
end
|
124
125
|
end
|
125
126
|
|
126
|
-
|
127
|
-
|
128
|
-
require 'sass/plugin/rails'
|
127
|
+
if defined?(ActionController)
|
128
|
+
# On Rails 3+ the rails plugin is loaded at the right time in railtie.rb
|
129
|
+
require 'sass/plugin/rails' unless Sass::Util.ap_geq_3?
|
129
130
|
elsif defined?(Merb::Plugins)
|
130
131
|
require 'sass/plugin/merb'
|
131
132
|
else
|