sass 3.2.7 → 3.3.0.rc.1
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.
- data/MIT-LICENSE +2 -2
- data/README.md +14 -2
- data/Rakefile +25 -1
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/VERSION_NAME +1 -1
- data/lib/sass/cache_stores/base.rb +4 -2
- data/lib/sass/cache_stores/chain.rb +2 -1
- data/lib/sass/cache_stores/filesystem.rb +2 -6
- data/lib/sass/cache_stores/memory.rb +1 -1
- data/lib/sass/cache_stores/null.rb +2 -2
- data/lib/sass/callbacks.rb +1 -0
- data/lib/sass/css.rb +10 -10
- data/lib/sass/engine.rb +403 -150
- data/lib/sass/environment.rb +136 -57
- data/lib/sass/error.rb +7 -7
- data/lib/sass/exec.rb +123 -39
- data/lib/sass/features.rb +41 -0
- data/lib/sass/importers/base.rb +33 -2
- data/lib/sass/importers/deprecated_path.rb +45 -0
- data/lib/sass/importers/filesystem.rb +25 -14
- data/lib/sass/importers.rb +1 -0
- data/lib/sass/logger/base.rb +3 -3
- data/lib/sass/logger/log_level.rb +4 -6
- data/lib/sass/media.rb +19 -19
- data/lib/sass/plugin/compiler.rb +141 -101
- data/lib/sass/plugin/configuration.rb +18 -22
- data/lib/sass/plugin/merb.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +24 -8
- data/lib/sass/plugin.rb +4 -2
- data/lib/sass/repl.rb +3 -3
- data/lib/sass/script/css_lexer.rb +9 -4
- data/lib/sass/script/css_parser.rb +6 -2
- data/lib/sass/script/functions.rb +1343 -590
- data/lib/sass/script/lexer.rb +84 -52
- data/lib/sass/script/parser.rb +217 -97
- data/lib/sass/script/tree/funcall.rb +290 -0
- data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +34 -13
- data/lib/sass/script/tree/list_literal.rb +80 -0
- data/lib/sass/script/tree/literal.rb +47 -0
- data/lib/sass/script/tree/map_literal.rb +64 -0
- data/lib/sass/script/{node.rb → tree/node.rb} +22 -12
- data/lib/sass/script/{operation.rb → tree/operation.rb} +17 -25
- data/lib/sass/script/tree/selector.rb +30 -0
- data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +5 -4
- data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +14 -9
- data/lib/sass/script/tree/variable.rb +57 -0
- data/lib/sass/script/tree.rb +16 -0
- data/lib/sass/script/{arg_list.rb → value/arg_list.rb} +4 -24
- data/lib/sass/script/value/base.rb +248 -0
- data/lib/sass/script/value/bool.rb +36 -0
- data/lib/sass/script/{color.rb → value/color.rb} +239 -195
- data/lib/sass/script/value/helpers.rb +155 -0
- data/lib/sass/script/value/list.rb +119 -0
- data/lib/sass/script/value/map.rb +70 -0
- data/lib/sass/script/value/null.rb +45 -0
- data/lib/sass/script/{number.rb → value/number.rb} +91 -65
- data/lib/sass/script/{string.rb → value/string.rb} +9 -11
- data/lib/sass/script/value.rb +11 -0
- data/lib/sass/script.rb +35 -8
- data/lib/sass/scss/css_parser.rb +2 -1
- data/lib/sass/scss/parser.rb +338 -170
- data/lib/sass/scss/rx.rb +5 -6
- data/lib/sass/scss/script_lexer.rb +1 -0
- data/lib/sass/scss/script_parser.rb +1 -0
- data/lib/sass/scss/static_parser.rb +23 -6
- data/lib/sass/selector/abstract_sequence.rb +2 -2
- data/lib/sass/selector/comma_sequence.rb +21 -16
- data/lib/sass/selector/sequence.rb +60 -34
- data/lib/sass/selector/simple.rb +11 -12
- data/lib/sass/selector/simple_sequence.rb +55 -33
- data/lib/sass/selector.rb +52 -48
- data/lib/sass/source/map.rb +211 -0
- data/lib/sass/source/position.rb +39 -0
- data/lib/sass/source/range.rb +41 -0
- data/lib/sass/stack.rb +120 -0
- data/lib/sass/supports.rb +12 -13
- data/lib/sass/tree/at_root_node.rb +82 -0
- data/lib/sass/tree/comment_node.rb +3 -3
- data/lib/sass/tree/css_import_node.rb +11 -11
- data/lib/sass/tree/debug_node.rb +2 -2
- data/lib/sass/tree/directive_node.rb +13 -2
- data/lib/sass/tree/each_node.rb +8 -8
- data/lib/sass/tree/extend_node.rb +13 -6
- data/lib/sass/tree/for_node.rb +4 -4
- data/lib/sass/tree/function_node.rb +5 -4
- data/lib/sass/tree/if_node.rb +1 -1
- data/lib/sass/tree/import_node.rb +4 -5
- data/lib/sass/tree/media_node.rb +4 -14
- data/lib/sass/tree/mixin_def_node.rb +4 -4
- data/lib/sass/tree/mixin_node.rb +21 -8
- data/lib/sass/tree/node.rb +29 -12
- data/lib/sass/tree/prop_node.rb +38 -18
- data/lib/sass/tree/return_node.rb +3 -2
- data/lib/sass/tree/root_node.rb +19 -3
- data/lib/sass/tree/rule_node.rb +25 -17
- data/lib/sass/tree/supports_node.rb +0 -13
- data/lib/sass/tree/trace_node.rb +2 -1
- data/lib/sass/tree/variable_node.rb +9 -3
- data/lib/sass/tree/visitors/base.rb +6 -6
- data/lib/sass/tree/visitors/check_nesting.rb +12 -9
- data/lib/sass/tree/visitors/convert.rb +63 -38
- data/lib/sass/tree/visitors/cssize.rb +63 -23
- data/lib/sass/tree/visitors/deep_copy.rb +6 -5
- data/lib/sass/tree/visitors/extend.rb +7 -7
- data/lib/sass/tree/visitors/perform.rb +256 -151
- data/lib/sass/tree/visitors/set_options.rb +6 -6
- data/lib/sass/tree/visitors/to_css.rb +231 -81
- data/lib/sass/tree/warn_node.rb +2 -2
- data/lib/sass/tree/while_node.rb +2 -2
- data/lib/sass/util/multibyte_string_scanner.rb +2 -0
- data/lib/sass/util/normalized_map.rb +65 -0
- data/lib/sass/util/ordered_hash.rb +188 -0
- data/lib/sass/util/subset_map.rb +3 -2
- data/lib/sass/util/test.rb +9 -0
- data/lib/sass/util.rb +220 -34
- data/lib/sass/version.rb +9 -9
- data/lib/sass.rb +14 -7
- data/test/sass/compiler_test.rb +213 -0
- data/test/sass/conversion_test.rb +235 -9
- data/test/sass/engine_test.rb +230 -60
- data/test/sass/exec_test.rb +86 -0
- data/test/sass/extend_test.rb +215 -147
- data/test/sass/functions_test.rb +584 -99
- data/test/sass/importer_test.rb +165 -17
- data/test/sass/plugin_test.rb +19 -13
- data/test/sass/script_conversion_test.rb +40 -0
- data/test/sass/script_test.rb +231 -21
- data/test/sass/scss/css_test.rb +14 -5
- data/test/sass/scss/scss_test.rb +1266 -66
- data/test/sass/source_map_test.rb +879 -0
- data/test/sass/templates/bork5.sass +3 -0
- data/test/sass/util/normalized_map_test.rb +30 -0
- data/test/sass/util_test.rb +90 -0
- data/test/sass/value_helpers_test.rb +181 -0
- data/test/test_helper.rb +7 -2
- metadata +316 -291
- data/lib/sass/script/bool.rb +0 -18
- data/lib/sass/script/funcall.rb +0 -231
- data/lib/sass/script/list.rb +0 -84
- data/lib/sass/script/literal.rb +0 -239
- data/lib/sass/script/null.rb +0 -34
- data/lib/sass/script/variable.rb +0 -58
- data/test/Gemfile +0 -3
- data/vendor/listen/CHANGELOG.md +0 -221
- data/vendor/listen/CONTRIBUTING.md +0 -38
- data/vendor/listen/Gemfile +0 -30
- data/vendor/listen/Guardfile +0 -8
- data/vendor/listen/LICENSE +0 -20
- data/vendor/listen/README.md +0 -315
- data/vendor/listen/Rakefile +0 -47
- data/vendor/listen/Vagrantfile +0 -96
- data/vendor/listen/lib/listen/adapter.rb +0 -214
- data/vendor/listen/lib/listen/adapters/bsd.rb +0 -112
- data/vendor/listen/lib/listen/adapters/darwin.rb +0 -85
- data/vendor/listen/lib/listen/adapters/linux.rb +0 -113
- data/vendor/listen/lib/listen/adapters/polling.rb +0 -67
- data/vendor/listen/lib/listen/adapters/windows.rb +0 -87
- data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
- data/vendor/listen/lib/listen/directory_record.rb +0 -371
- data/vendor/listen/lib/listen/listener.rb +0 -225
- data/vendor/listen/lib/listen/multi_listener.rb +0 -143
- data/vendor/listen/lib/listen/turnstile.rb +0 -28
- data/vendor/listen/lib/listen/version.rb +0 -3
- data/vendor/listen/lib/listen.rb +0 -40
- data/vendor/listen/listen.gemspec +0 -22
- data/vendor/listen/spec/listen/adapter_spec.rb +0 -183
- data/vendor/listen/spec/listen/adapters/bsd_spec.rb +0 -36
- data/vendor/listen/spec/listen/adapters/darwin_spec.rb +0 -37
- data/vendor/listen/spec/listen/adapters/linux_spec.rb +0 -47
- data/vendor/listen/spec/listen/adapters/polling_spec.rb +0 -68
- data/vendor/listen/spec/listen/adapters/windows_spec.rb +0 -30
- data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
- data/vendor/listen/spec/listen/directory_record_spec.rb +0 -1225
- data/vendor/listen/spec/listen/listener_spec.rb +0 -169
- data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
- data/vendor/listen/spec/listen/turnstile_spec.rb +0 -56
- data/vendor/listen/spec/listen_spec.rb +0 -73
- data/vendor/listen/spec/spec_helper.rb +0 -21
- data/vendor/listen/spec/support/adapter_helper.rb +0 -629
- data/vendor/listen/spec/support/directory_record_helper.rb +0 -55
- data/vendor/listen/spec/support/fixtures_helper.rb +0 -29
- data/vendor/listen/spec/support/listeners_helper.rb +0 -156
- data/vendor/listen/spec/support/platform_helper.rb +0 -15
data/lib/sass/plugin/compiler.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'fileutils'
|
|
2
|
+
require 'pathname'
|
|
2
3
|
|
|
3
4
|
require 'sass'
|
|
4
5
|
# XXX CE: is this still necessary now that we have the compiler class?
|
|
@@ -32,10 +33,10 @@ module Sass::Plugin
|
|
|
32
33
|
|
|
33
34
|
# Creates a new compiler.
|
|
34
35
|
#
|
|
35
|
-
# @param
|
|
36
|
+
# @param opts [{Symbol => Object}]
|
|
36
37
|
# See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
|
|
37
|
-
def initialize(
|
|
38
|
-
|
|
38
|
+
def initialize(opts = {})
|
|
39
|
+
options.merge!(opts)
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
# Register a callback to be run after stylesheets are mass-updated.
|
|
@@ -65,31 +66,10 @@ module Sass::Plugin
|
|
|
65
66
|
# The location of the Sass/SCSS file being updated.
|
|
66
67
|
# @yieldparam css [String]
|
|
67
68
|
# The location of the CSS file being generated.
|
|
69
|
+
# @yieldparam sourcemap [String]
|
|
70
|
+
# The location of the sourcemap being generated, if any.
|
|
68
71
|
define_callback :updated_stylesheet
|
|
69
72
|
|
|
70
|
-
# Register a callback to be run before a single stylesheet is updated.
|
|
71
|
-
# The callback is only run if the stylesheet is guaranteed to be updated;
|
|
72
|
-
# if the CSS file is fresh, this won't be run.
|
|
73
|
-
#
|
|
74
|
-
# Even if the \{file:SASS_REFERENCE.md#full_exception-option `:full_exception` option}
|
|
75
|
-
# is enabled, this callback won't be run
|
|
76
|
-
# when an exception CSS file is being written.
|
|
77
|
-
# To run an action for those files, use \{#on\_compilation\_error}.
|
|
78
|
-
#
|
|
79
|
-
# @yield [template, css]
|
|
80
|
-
# @yieldparam template [String]
|
|
81
|
-
# The location of the Sass/SCSS file being updated.
|
|
82
|
-
# @yieldparam css [String]
|
|
83
|
-
# The location of the CSS file being generated.
|
|
84
|
-
define_callback :updating_stylesheet
|
|
85
|
-
|
|
86
|
-
def on_updating_stylesheet_with_deprecation_warning(&block)
|
|
87
|
-
Sass::Util.sass_warn("Sass::Compiler#on_updating_stylesheet callback is deprecated and will be removed in a future release. Use Sass::Compiler#on_updated_stylesheet instead, which is run after stylesheet compilation.")
|
|
88
|
-
on_updating_stylesheet_without_deprecation_warning(&block)
|
|
89
|
-
end
|
|
90
|
-
alias_method :on_updating_stylesheet_without_deprecation_warning, :on_updating_stylesheet
|
|
91
|
-
alias_method :on_updating_stylesheet, :on_updating_stylesheet_with_deprecation_warning
|
|
92
|
-
|
|
93
73
|
# Register a callback to be run when Sass decides not to update a stylesheet.
|
|
94
74
|
# In particular, the callback is run when Sass finds that
|
|
95
75
|
# the template file and none of its dependencies
|
|
@@ -169,9 +149,18 @@ module Sass::Plugin
|
|
|
169
149
|
# The location of the CSS file that was deleted.
|
|
170
150
|
define_callback :deleting_css
|
|
171
151
|
|
|
152
|
+
# Register a callback to be run when Sass deletes a sourcemap file.
|
|
153
|
+
# This happens when the corresponding Sass/SCSS file has been deleted.
|
|
154
|
+
#
|
|
155
|
+
# @yield [filename]
|
|
156
|
+
# @yieldparam filename [String]
|
|
157
|
+
# The location of the sourcemap file that was deleted.
|
|
158
|
+
define_callback :deleting_sourcemap
|
|
159
|
+
|
|
172
160
|
# Updates out-of-date stylesheets.
|
|
173
161
|
#
|
|
174
|
-
# Checks each Sass/SCSS file in
|
|
162
|
+
# Checks each Sass/SCSS file in
|
|
163
|
+
# {file:SASS_REFERENCE.md#template_location-option `:template_location`}
|
|
175
164
|
# to see if it's been modified more recently than the corresponding CSS file
|
|
176
165
|
# in {file:SASS_REFERENCE.md#css_location-option `:css_location`}.
|
|
177
166
|
# If it has, it updates the CSS file.
|
|
@@ -192,17 +181,17 @@ module Sass::Plugin
|
|
|
192
181
|
# Get the relative path to the file
|
|
193
182
|
name = file.sub(template_location.to_s.sub(/\/*$/, '/'), "")
|
|
194
183
|
css = css_filename(name, css_location)
|
|
195
|
-
|
|
184
|
+
sourcemap = Sass::Util.sourcemap_name(css) if engine_options[:sourcemap]
|
|
185
|
+
individual_files << [file, css, sourcemap]
|
|
196
186
|
end
|
|
197
187
|
end
|
|
198
188
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
individual_files.each do |file, css|
|
|
189
|
+
individual_files.each do |file, css, sourcemap|
|
|
190
|
+
# TODO: Does staleness_checker need to check the sourcemap file as well?
|
|
202
191
|
if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
|
|
203
|
-
update_stylesheet(file, css)
|
|
192
|
+
update_stylesheet(file, css, sourcemap)
|
|
204
193
|
else
|
|
205
|
-
run_not_updating_stylesheet(file, css)
|
|
194
|
+
run_not_updating_stylesheet(file, css, sourcemap)
|
|
206
195
|
end
|
|
207
196
|
end
|
|
208
197
|
end
|
|
@@ -234,80 +223,72 @@ module Sass::Plugin
|
|
|
234
223
|
def watch(individual_files = [])
|
|
235
224
|
update_stylesheets(individual_files)
|
|
236
225
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
dir = Sass::Util.scope("vendor/listen/lib")
|
|
241
|
-
if $LOAD_PATH.include?(dir)
|
|
242
|
-
e.message << "\n" <<
|
|
243
|
-
if File.exists?(scope(".git"))
|
|
244
|
-
'Run "git submodule update --init" to get the recommended version.'
|
|
245
|
-
else
|
|
246
|
-
'Run "gem install listen" to get it.'
|
|
247
|
-
end
|
|
248
|
-
raise e
|
|
249
|
-
else
|
|
250
|
-
$LOAD_PATH.unshift dir
|
|
251
|
-
retry
|
|
252
|
-
end
|
|
226
|
+
directories = watched_paths
|
|
227
|
+
individual_files.each do |(source, _, _)|
|
|
228
|
+
directories << File.dirname(File.expand_path(source))
|
|
253
229
|
end
|
|
254
|
-
|
|
255
|
-
template_paths = template_locations # cache the locations
|
|
256
|
-
individual_files_hash = individual_files.inject({}) do |h, files|
|
|
257
|
-
parent = File.dirname(files.first)
|
|
258
|
-
(h[parent] ||= []) << files unless template_paths.include?(parent)
|
|
259
|
-
h
|
|
260
|
-
end
|
|
261
|
-
directories = template_paths + individual_files_hash.keys +
|
|
262
|
-
[{:relative_paths => true}]
|
|
230
|
+
directories = remove_redundant_directories(directories)
|
|
263
231
|
|
|
264
232
|
# TODO: Keep better track of what depends on what
|
|
265
233
|
# so we don't have to run a global update every time anything changes.
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
run_template_modified(f)
|
|
234
|
+
listener_args = directories + [{:relative_paths => false}]
|
|
235
|
+
listener = create_listener(*listener_args) do |modified, added, removed|
|
|
236
|
+
recompile_required = false
|
|
237
|
+
|
|
238
|
+
modified.uniq.each do |f|
|
|
239
|
+
next unless watched_file?(f)
|
|
240
|
+
recompile_required = true
|
|
241
|
+
run_template_modified(relative_to_pwd(f))
|
|
275
242
|
end
|
|
276
243
|
|
|
277
|
-
added.each do |f|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
else
|
|
282
|
-
next unless f =~ /\.s[ac]ss$/
|
|
283
|
-
end
|
|
284
|
-
run_template_created(f)
|
|
244
|
+
added.uniq.each do |f|
|
|
245
|
+
next unless watched_file?(f)
|
|
246
|
+
recompile_required = true
|
|
247
|
+
run_template_created(relative_to_pwd(f))
|
|
285
248
|
end
|
|
286
249
|
|
|
287
|
-
removed.each do |f|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
250
|
+
removed.uniq.each do |f|
|
|
251
|
+
if (files = individual_files.find {|(source, _, _)| File.expand_path(source) == f})
|
|
252
|
+
recompile_required = true
|
|
253
|
+
# This was a file we were watching explicitly and compiling to a particular location.
|
|
254
|
+
# Delete the corresponding file.
|
|
291
255
|
try_delete_css files[1]
|
|
292
256
|
else
|
|
293
|
-
next unless f
|
|
294
|
-
|
|
257
|
+
next unless watched_file?(f)
|
|
258
|
+
recompile_required = true
|
|
259
|
+
# Look for the sass directory that contained the sass file
|
|
260
|
+
# And try to remove the css file that corresponds to it
|
|
261
|
+
template_location_array.each do |(sass_dir, css_dir)|
|
|
262
|
+
sass_dir = File.expand_path(sass_dir)
|
|
263
|
+
if child_of_directory?(sass_dir, f)
|
|
264
|
+
remainder = f[(sass_dir.size + 1)..-1]
|
|
265
|
+
try_delete_css(css_filename(remainder, css_dir))
|
|
266
|
+
break
|
|
267
|
+
end
|
|
268
|
+
end
|
|
295
269
|
end
|
|
296
|
-
run_template_deleted(f)
|
|
270
|
+
run_template_deleted(relative_to_pwd(f))
|
|
297
271
|
end
|
|
298
272
|
|
|
299
|
-
|
|
273
|
+
if recompile_required
|
|
274
|
+
# In case a file we're watching is removed and then recreated we
|
|
275
|
+
# prune out the non-existant files here.
|
|
276
|
+
watched_files_remaining = individual_files.select {|(source, _, _)| File.exists?(source)}
|
|
277
|
+
update_stylesheets(watched_files_remaining)
|
|
278
|
+
end
|
|
300
279
|
end
|
|
301
280
|
|
|
302
|
-
# The native windows listener is much slower than the polling
|
|
303
|
-
#
|
|
281
|
+
# The native windows listener is much slower than the polling option, according to
|
|
282
|
+
# https://github.com/nex3/sass/commit/a3031856b22bc834a5417dedecb038b7be9b9e3e
|
|
304
283
|
listener.force_polling(true) if @options[:poll] || Sass::Util.windows?
|
|
305
284
|
|
|
285
|
+
# rubocop:disable RescueException
|
|
306
286
|
begin
|
|
307
|
-
listener.start
|
|
287
|
+
listener.start!
|
|
308
288
|
rescue Exception => e
|
|
309
289
|
raise e unless e.is_a?(Interrupt)
|
|
310
290
|
end
|
|
291
|
+
# rubocop:enable RescueException
|
|
311
292
|
end
|
|
312
293
|
|
|
313
294
|
# Non-destructively modifies \{#options} so that default values are properly set,
|
|
@@ -328,7 +309,28 @@ module Sass::Plugin
|
|
|
328
309
|
|
|
329
310
|
private
|
|
330
311
|
|
|
331
|
-
def
|
|
312
|
+
def create_listener(*args, &block)
|
|
313
|
+
require 'listen'
|
|
314
|
+
Listen::Listener.new(*args, &block)
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def remove_redundant_directories(directories)
|
|
318
|
+
dedupped = []
|
|
319
|
+
directories.each do |new_directory|
|
|
320
|
+
# no need to add a directory that is already watched.
|
|
321
|
+
next if dedupped.any? do |existing_directory|
|
|
322
|
+
child_of_directory?(existing_directory, new_directory)
|
|
323
|
+
end
|
|
324
|
+
# get rid of any sub directories of this new directory
|
|
325
|
+
dedupped.reject! do |existing_directory|
|
|
326
|
+
child_of_directory?(new_directory, existing_directory)
|
|
327
|
+
end
|
|
328
|
+
dedupped << new_directory
|
|
329
|
+
end
|
|
330
|
+
dedupped
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def update_stylesheet(filename, css, sourcemap)
|
|
332
334
|
dir = File.dirname(css)
|
|
333
335
|
unless File.exists?(dir)
|
|
334
336
|
run_creating_directory dir
|
|
@@ -338,32 +340,58 @@ module Sass::Plugin
|
|
|
338
340
|
begin
|
|
339
341
|
File.read(filename) unless File.readable?(filename) # triggers an error for handling
|
|
340
342
|
engine_opts = engine_options(:css_filename => css, :filename => filename)
|
|
341
|
-
|
|
342
|
-
|
|
343
|
+
mapping = nil
|
|
344
|
+
engine = Sass::Engine.for_file(filename, engine_opts)
|
|
345
|
+
if sourcemap
|
|
346
|
+
rendered, mapping = engine.render_with_sourcemap(File.basename(sourcemap))
|
|
347
|
+
else
|
|
348
|
+
rendered = engine.render
|
|
349
|
+
end
|
|
350
|
+
rescue StandardError => e
|
|
343
351
|
compilation_error_occured = true
|
|
344
|
-
run_compilation_error e, filename, css
|
|
345
|
-
|
|
346
|
-
else
|
|
347
|
-
run_updating_stylesheet filename, css
|
|
352
|
+
run_compilation_error e, filename, css, sourcemap
|
|
353
|
+
rendered = Sass::SyntaxError.exception_to_css(e, options)
|
|
348
354
|
end
|
|
349
355
|
|
|
350
|
-
write_file(css,
|
|
351
|
-
|
|
356
|
+
write_file(css, rendered)
|
|
357
|
+
if mapping
|
|
358
|
+
write_file(sourcemap, mapping.to_json(:css_path => css, :sourcemap_path => sourcemap))
|
|
359
|
+
end
|
|
360
|
+
run_updated_stylesheet(filename, css, sourcemap) unless compilation_error_occured
|
|
352
361
|
end
|
|
353
362
|
|
|
354
|
-
def write_file(
|
|
363
|
+
def write_file(fileName, content)
|
|
355
364
|
flag = 'w'
|
|
356
365
|
flag = 'wb' if Sass::Util.windows? && options[:unix_newlines]
|
|
357
|
-
File.open(
|
|
366
|
+
File.open(fileName, flag) do |file|
|
|
358
367
|
file.set_encoding(content.encoding) unless Sass::Util.ruby1_8?
|
|
359
368
|
file.print(content)
|
|
360
369
|
end
|
|
361
370
|
end
|
|
362
371
|
|
|
363
372
|
def try_delete_css(css)
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
373
|
+
if File.exists?(css)
|
|
374
|
+
run_deleting_css css
|
|
375
|
+
File.delete css
|
|
376
|
+
end
|
|
377
|
+
map = Sass::Util.sourcemap_name(css)
|
|
378
|
+
if File.exists?(map)
|
|
379
|
+
run_deleting_sourcemap map
|
|
380
|
+
File.delete map
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def watched_file?(file)
|
|
385
|
+
normalized_load_paths.find {|lp| lp.watched_file?(file)}
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def watched_paths
|
|
389
|
+
@watched_paths ||= normalized_load_paths.map {|lp| lp.directories_to_watch}.compact.flatten
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def normalized_load_paths
|
|
393
|
+
@normalized_load_paths ||=
|
|
394
|
+
Sass::Engine.normalize_options(:load_paths => load_paths)[:load_paths]
|
|
367
395
|
end
|
|
368
396
|
|
|
369
397
|
def load_paths(opts = options)
|
|
@@ -379,7 +407,19 @@ module Sass::Plugin
|
|
|
379
407
|
end
|
|
380
408
|
|
|
381
409
|
def css_filename(name, path)
|
|
382
|
-
"#{path}
|
|
410
|
+
"#{path}#{File::SEPARATOR unless path.end_with?(File::SEPARATOR)}#{name}".
|
|
411
|
+
gsub(/\.s[ac]ss$/, '.css')
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
def relative_to_pwd(f)
|
|
415
|
+
Pathname.new(f).relative_path_from(Pathname.new(Dir.pwd)).to_s
|
|
416
|
+
rescue ArgumentError # when a relative path cannot be computed
|
|
417
|
+
f
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
def child_of_directory?(parent, child)
|
|
421
|
+
parent_dir = parent.end_with?(File::SEPARATOR) ? parent : (parent + File::SEPARATOR)
|
|
422
|
+
child.start_with?(parent_dir) || parent == child
|
|
383
423
|
end
|
|
384
424
|
end
|
|
385
425
|
end
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
# We keep configuration in its own self-contained file
|
|
2
|
-
# so that we can load it independently in Rails 3,
|
|
3
|
-
# where the full plugin stuff is lazy-loaded.
|
|
4
|
-
|
|
5
1
|
module Sass
|
|
6
2
|
module Plugin
|
|
3
|
+
# We keep configuration in its own self-contained file
|
|
4
|
+
# so that we can load it independently in Rails 3,
|
|
5
|
+
# where the full plugin stuff is lazy-loaded.
|
|
7
6
|
module Configuration
|
|
8
7
|
|
|
9
8
|
# Returns the default options for a {Sass::Plugin::Compiler}.
|
|
@@ -19,7 +18,8 @@ module Sass
|
|
|
19
18
|
}.freeze
|
|
20
19
|
end
|
|
21
20
|
|
|
22
|
-
# Resets the options and
|
|
21
|
+
# Resets the options and
|
|
22
|
+
# {Sass::Callbacks::InstanceMethods#clear_callbacks! clears all callbacks}.
|
|
23
23
|
def reset!
|
|
24
24
|
@options = nil
|
|
25
25
|
clear_callbacks!
|
|
@@ -33,22 +33,12 @@ module Sass
|
|
|
33
33
|
@options ||= default_options.dup
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
# Sets the options hash.
|
|
37
|
-
# See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
|
|
38
|
-
# See {Sass::Plugin::Configuration#reset!}
|
|
39
|
-
# @deprecated Instead, modify the options hash in-place.
|
|
40
|
-
# @param value [{Symbol => Object}] The options hash
|
|
41
|
-
def options=(value)
|
|
42
|
-
Sass::Util.sass_warn("Setting Sass::Plugin.options is deprecated " +
|
|
43
|
-
"and will be removed in a future release.")
|
|
44
|
-
options.merge!(value)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
36
|
# Adds a new template-location/css-location mapping.
|
|
48
37
|
# This means that Sass/SCSS files in `template_location`
|
|
49
38
|
# will be compiled to CSS files in `css_location`.
|
|
50
39
|
#
|
|
51
|
-
# This is preferred over manually manipulating the
|
|
40
|
+
# This is preferred over manually manipulating the
|
|
41
|
+
# {file:SASS_REFERENCE.md#template_location-option `:template_location` option}
|
|
52
42
|
# since the option can be in multiple formats.
|
|
53
43
|
#
|
|
54
44
|
# Note that this method will change `options[:template_location]`
|
|
@@ -68,7 +58,8 @@ module Sass
|
|
|
68
58
|
# This means that Sass/SCSS files in `template_location`
|
|
69
59
|
# will no longer be compiled to CSS files in `css_location`.
|
|
70
60
|
#
|
|
71
|
-
# This is preferred over manually manipulating the
|
|
61
|
+
# This is preferred over manually manipulating the
|
|
62
|
+
# {file:SASS_REFERENCE.md#template_location-option `:template_location` option}
|
|
72
63
|
# since the option can be in multiple formats.
|
|
73
64
|
#
|
|
74
65
|
# Note that this method will change `options[:template_location]`
|
|
@@ -112,10 +103,15 @@ module Sass
|
|
|
112
103
|
options[:template_location] =
|
|
113
104
|
case options[:template_location]
|
|
114
105
|
when nil
|
|
115
|
-
options[:css_location]
|
|
116
|
-
[[File.join(options[:css_location], 'sass'), options[:css_location]]]
|
|
117
|
-
|
|
118
|
-
|
|
106
|
+
if options[:css_location]
|
|
107
|
+
[[File.join(options[:css_location], 'sass'), options[:css_location]]]
|
|
108
|
+
else
|
|
109
|
+
[]
|
|
110
|
+
end
|
|
111
|
+
when String
|
|
112
|
+
[[options[:template_location], options[:css_location]]]
|
|
113
|
+
else
|
|
114
|
+
options[:template_location].to_a
|
|
119
115
|
end
|
|
120
116
|
end
|
|
121
117
|
end
|
data/lib/sass/plugin/merb.rb
CHANGED
|
@@ -5,7 +5,7 @@ unless defined?(Sass::MERB_LOADED)
|
|
|
5
5
|
# Different default options in a m envirionment.
|
|
6
6
|
def default_options
|
|
7
7
|
@default_options ||= begin
|
|
8
|
-
version = Merb::VERSION.split('.').map {
|
|
8
|
+
version = Merb::VERSION.split('.').map {|n| n.to_i}
|
|
9
9
|
if version[0] <= 0 && version[1] < 5
|
|
10
10
|
root = MERB_ROOT
|
|
11
11
|
env = MERB_ENV
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
|
|
1
3
|
module Sass
|
|
2
4
|
module Plugin
|
|
3
5
|
# The class handles `.s[ca]ss` file staleness checks via their mtime timestamps.
|
|
@@ -24,11 +26,13 @@ module Sass
|
|
|
24
26
|
# as its instance-level caches are never explicitly expired.
|
|
25
27
|
class StalenessChecker
|
|
26
28
|
@dependencies_cache = {}
|
|
29
|
+
@dependency_cache_mutex = Mutex.new
|
|
27
30
|
|
|
28
31
|
class << self
|
|
29
32
|
# TODO: attach this to a compiler instance.
|
|
30
33
|
# @private
|
|
31
34
|
attr_accessor :dependencies_cache
|
|
35
|
+
attr_reader :dependency_cache_mutex
|
|
32
36
|
end
|
|
33
37
|
|
|
34
38
|
# Creates a new StalenessChecker
|
|
@@ -37,15 +41,13 @@ module Sass
|
|
|
37
41
|
# @param options [{Symbol => Object}]
|
|
38
42
|
# See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
|
|
39
43
|
def initialize(options)
|
|
40
|
-
@dependencies = self.class.dependencies_cache
|
|
41
|
-
|
|
42
44
|
# URIs that are being actively checked for staleness. Protects against
|
|
43
45
|
# import loops.
|
|
44
46
|
@actively_checking = Set.new
|
|
45
47
|
|
|
46
48
|
# Entries in the following instance-level caches are never explicitly expired.
|
|
47
|
-
# Instead they are supposed to automaticaly go out of scope when a series of staleness
|
|
48
|
-
# (this instance of StalenessChecker was created for) is finished.
|
|
49
|
+
# Instead they are supposed to automaticaly go out of scope when a series of staleness
|
|
50
|
+
# checks (this instance of StalenessChecker was created for) is finished.
|
|
49
51
|
@mtimes, @dependencies_stale, @parse_trees = {}, {}, {}
|
|
50
52
|
@options = Sass::Engine.normalize_options(options)
|
|
51
53
|
end
|
|
@@ -131,7 +133,7 @@ module Sass
|
|
|
131
133
|
begin
|
|
132
134
|
mtime = importer.mtime(uri, @options)
|
|
133
135
|
if mtime.nil?
|
|
134
|
-
|
|
136
|
+
with_dependency_cache {|cache| cache.delete([uri, importer])}
|
|
135
137
|
nil
|
|
136
138
|
else
|
|
137
139
|
mtime
|
|
@@ -140,18 +142,21 @@ module Sass
|
|
|
140
142
|
end
|
|
141
143
|
|
|
142
144
|
def dependencies(uri, importer)
|
|
143
|
-
stored_mtime, dependencies =
|
|
145
|
+
stored_mtime, dependencies =
|
|
146
|
+
with_dependency_cache {|cache| Sass::Util.destructure(cache[[uri, importer]])}
|
|
144
147
|
|
|
145
148
|
if !stored_mtime || stored_mtime < mtime(uri, importer)
|
|
146
149
|
dependencies = compute_dependencies(uri, importer)
|
|
147
|
-
|
|
150
|
+
with_dependency_cache do |cache|
|
|
151
|
+
cache[[uri, importer]] = [mtime(uri, importer), dependencies]
|
|
152
|
+
end
|
|
148
153
|
end
|
|
149
154
|
|
|
150
155
|
dependencies
|
|
151
156
|
end
|
|
152
157
|
|
|
153
158
|
def dependency_updated?(css_mtime)
|
|
154
|
-
|
|
159
|
+
proc do |uri, importer|
|
|
155
160
|
next true if @actively_checking.include?(uri)
|
|
156
161
|
begin
|
|
157
162
|
@actively_checking << uri
|
|
@@ -178,6 +183,17 @@ module Sass
|
|
|
178
183
|
def tree(uri, importer)
|
|
179
184
|
@parse_trees[[uri, importer]] ||= importer.find(uri, @options).to_tree
|
|
180
185
|
end
|
|
186
|
+
|
|
187
|
+
# Get access to the global dependency cache in a threadsafe manner.
|
|
188
|
+
# Inside the block, no other thread can access the dependency cache.
|
|
189
|
+
#
|
|
190
|
+
# @yieldparam cache [Hash] The hash that is the global dependency cache
|
|
191
|
+
# @return The value returned by the block to which this method yields
|
|
192
|
+
def with_dependency_cache
|
|
193
|
+
StalenessChecker.dependency_cache_mutex.synchronize do
|
|
194
|
+
yield StalenessChecker.dependencies_cache
|
|
195
|
+
end
|
|
196
|
+
end
|
|
181
197
|
end
|
|
182
198
|
end
|
|
183
199
|
end
|
data/lib/sass/plugin.rb
CHANGED
|
@@ -11,7 +11,8 @@ module Sass
|
|
|
11
11
|
# This module is used as the primary interface with 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
|
-
# The plugin is
|
|
14
|
+
# The plugin is
|
|
15
|
+
# {file:SASS_REFERENCE.md#rails_merb_plugin automatically activated for Rails and Merb}.
|
|
15
16
|
# Other frameworks must enable it explicitly; see {Sass::Plugin::Rack}.
|
|
16
17
|
#
|
|
17
18
|
# This module has a large set of callbacks available
|
|
@@ -65,7 +66,8 @@ module Sass
|
|
|
65
66
|
|
|
66
67
|
# Updates out-of-date stylesheets.
|
|
67
68
|
#
|
|
68
|
-
# Checks each Sass/SCSS file in
|
|
69
|
+
# Checks each Sass/SCSS file in
|
|
70
|
+
# {file:SASS_REFERENCE.md#template_location-option `:template_location`}
|
|
69
71
|
# to see if it's been modified more recently than the corresponding CSS file
|
|
70
72
|
# in {file:SASS_REFERENCE.md#css_location-option `:css_location`}.
|
|
71
73
|
# If it has, it updates the CSS file.
|
data/lib/sass/repl.rb
CHANGED
|
@@ -18,7 +18,7 @@ module Sass
|
|
|
18
18
|
@line = 0
|
|
19
19
|
loop do
|
|
20
20
|
@line += 1
|
|
21
|
-
unless text = Readline.readline('>> ')
|
|
21
|
+
unless (text = Readline.readline('>> '))
|
|
22
22
|
puts
|
|
23
23
|
return
|
|
24
24
|
end
|
|
@@ -48,8 +48,8 @@ module Sass
|
|
|
48
48
|
rescue Sass::SyntaxError => e
|
|
49
49
|
puts "SyntaxError: #{e.message}"
|
|
50
50
|
if @options[:trace]
|
|
51
|
-
e.backtrace.each do |
|
|
52
|
-
puts "\tfrom #{
|
|
51
|
+
e.backtrace.each do |line|
|
|
52
|
+
puts "\tfrom #{line}"
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
55
|
end
|
|
@@ -4,6 +4,7 @@ module Sass
|
|
|
4
4
|
#
|
|
5
5
|
# @see Sass::SCSS::CssParser
|
|
6
6
|
class CssLexer < Lexer
|
|
7
|
+
|
|
7
8
|
private
|
|
8
9
|
|
|
9
10
|
def token
|
|
@@ -12,16 +13,20 @@ module Sass
|
|
|
12
13
|
|
|
13
14
|
def string(re, *args)
|
|
14
15
|
if re == :uri
|
|
15
|
-
|
|
16
|
-
return
|
|
16
|
+
uri = scan(URI)
|
|
17
|
+
return unless uri
|
|
18
|
+
return [:string, Script::Value::String.new(uri)]
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
return unless scan(STRING)
|
|
20
|
-
|
|
22
|
+
string_value = (@scanner[1] || @scanner[2]).gsub(/\\(['"])/, '\1')
|
|
23
|
+
value = Script::Value::String.new(string_value, :string)
|
|
24
|
+
[:string, value]
|
|
21
25
|
end
|
|
22
26
|
|
|
23
27
|
def important
|
|
24
|
-
|
|
28
|
+
s = scan(IMPORTANT)
|
|
29
|
+
return unless s
|
|
25
30
|
[:raw, s]
|
|
26
31
|
end
|
|
27
32
|
end
|
|
@@ -7,6 +7,7 @@ module Sass
|
|
|
7
7
|
#
|
|
8
8
|
# @see Sass::SCSS::CssParser
|
|
9
9
|
class CssParser < Parser
|
|
10
|
+
|
|
10
11
|
private
|
|
11
12
|
|
|
12
13
|
# @private
|
|
@@ -17,8 +18,11 @@ module Sass
|
|
|
17
18
|
production :div, :unary_plus, :div
|
|
18
19
|
|
|
19
20
|
def string
|
|
20
|
-
|
|
21
|
-
return
|
|
21
|
+
tok = try_tok(:string)
|
|
22
|
+
return number unless tok
|
|
23
|
+
unless @lexer.peek && @lexer.peek.type == :begin_interpolation
|
|
24
|
+
return literal_node(tok.value, tok.source_range)
|
|
25
|
+
end
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
# Short-circuit all the SassScript-only productions
|