sass 3.3.0 → 3.4.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|