sass 3.1.0 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CONTRIBUTING +1 -1
- data/MIT-LICENSE +2 -2
- data/README.md +29 -17
- data/Rakefile +43 -9
- data/VERSION +1 -1
- data/VERSION_DATE +1 -0
- data/VERSION_NAME +1 -1
- data/bin/sass +6 -1
- data/bin/sass-convert +6 -1
- data/bin/scss +6 -1
- data/ext/mkrf_conf.rb +27 -0
- data/lib/sass/cache_stores/base.rb +7 -3
- data/lib/sass/cache_stores/chain.rb +3 -2
- data/lib/sass/cache_stores/filesystem.rb +5 -7
- data/lib/sass/cache_stores/memory.rb +1 -1
- data/lib/sass/cache_stores/null.rb +2 -2
- data/lib/sass/callbacks.rb +2 -1
- data/lib/sass/css.rb +168 -53
- data/lib/sass/engine.rb +502 -174
- data/lib/sass/environment.rb +151 -111
- data/lib/sass/error.rb +7 -7
- data/lib/sass/exec.rb +176 -60
- data/lib/sass/features.rb +40 -0
- data/lib/sass/importers/base.rb +46 -7
- data/lib/sass/importers/deprecated_path.rb +51 -0
- data/lib/sass/importers/filesystem.rb +113 -30
- data/lib/sass/importers.rb +1 -0
- data/lib/sass/logger/base.rb +30 -0
- data/lib/sass/logger/log_level.rb +45 -0
- data/lib/sass/logger.rb +12 -0
- data/lib/sass/media.rb +213 -0
- data/lib/sass/plugin/compiler.rb +194 -104
- data/lib/sass/plugin/configuration.rb +18 -25
- data/lib/sass/plugin/merb.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +37 -11
- data/lib/sass/plugin.rb +10 -13
- data/lib/sass/railtie.rb +2 -1
- data/lib/sass/repl.rb +5 -6
- data/lib/sass/script/css_lexer.rb +8 -4
- data/lib/sass/script/css_parser.rb +5 -2
- data/lib/sass/script/functions.rb +1547 -618
- data/lib/sass/script/lexer.rb +122 -72
- data/lib/sass/script/parser.rb +304 -135
- data/lib/sass/script/tree/funcall.rb +306 -0
- data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
- data/lib/sass/script/tree/list_literal.rb +77 -0
- data/lib/sass/script/tree/literal.rb +45 -0
- data/lib/sass/script/tree/map_literal.rb +64 -0
- data/lib/sass/script/{node.rb → tree/node.rb} +30 -12
- data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
- data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
- data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
- data/lib/sass/script/tree/variable.rb +57 -0
- data/lib/sass/script/tree.rb +15 -0
- data/lib/sass/script/value/arg_list.rb +36 -0
- data/lib/sass/script/value/base.rb +238 -0
- data/lib/sass/script/value/bool.rb +40 -0
- data/lib/sass/script/{color.rb → value/color.rb} +256 -74
- data/lib/sass/script/value/deprecated_false.rb +55 -0
- data/lib/sass/script/value/helpers.rb +155 -0
- data/lib/sass/script/value/list.rb +128 -0
- data/lib/sass/script/value/map.rb +70 -0
- data/lib/sass/script/value/null.rb +49 -0
- data/lib/sass/script/{number.rb → value/number.rb} +115 -62
- data/lib/sass/script/{string.rb → value/string.rb} +9 -11
- data/lib/sass/script/value.rb +12 -0
- data/lib/sass/script.rb +35 -9
- data/lib/sass/scss/css_parser.rb +2 -12
- data/lib/sass/scss/parser.rb +657 -230
- data/lib/sass/scss/rx.rb +17 -12
- data/lib/sass/scss/static_parser.rb +37 -6
- data/lib/sass/scss.rb +0 -1
- data/lib/sass/selector/abstract_sequence.rb +35 -3
- data/lib/sass/selector/comma_sequence.rb +29 -14
- data/lib/sass/selector/sequence.rb +371 -74
- data/lib/sass/selector/simple.rb +28 -13
- data/lib/sass/selector/simple_sequence.rb +163 -36
- data/lib/sass/selector.rb +138 -36
- data/lib/sass/shared.rb +3 -5
- data/lib/sass/source/map.rb +196 -0
- data/lib/sass/source/position.rb +39 -0
- data/lib/sass/source/range.rb +41 -0
- data/lib/sass/stack.rb +126 -0
- data/lib/sass/supports.rb +228 -0
- data/lib/sass/tree/at_root_node.rb +82 -0
- data/lib/sass/tree/comment_node.rb +34 -29
- data/lib/sass/tree/content_node.rb +9 -0
- data/lib/sass/tree/css_import_node.rb +60 -0
- data/lib/sass/tree/debug_node.rb +3 -3
- data/lib/sass/tree/directive_node.rb +33 -3
- data/lib/sass/tree/each_node.rb +9 -9
- data/lib/sass/tree/extend_node.rb +20 -6
- data/lib/sass/tree/for_node.rb +6 -6
- data/lib/sass/tree/function_node.rb +12 -4
- data/lib/sass/tree/if_node.rb +2 -15
- data/lib/sass/tree/import_node.rb +11 -5
- data/lib/sass/tree/media_node.rb +27 -11
- data/lib/sass/tree/mixin_def_node.rb +15 -4
- data/lib/sass/tree/mixin_node.rb +27 -7
- data/lib/sass/tree/node.rb +69 -35
- data/lib/sass/tree/prop_node.rb +47 -31
- data/lib/sass/tree/return_node.rb +4 -3
- data/lib/sass/tree/root_node.rb +20 -4
- data/lib/sass/tree/rule_node.rb +37 -26
- data/lib/sass/tree/supports_node.rb +38 -0
- data/lib/sass/tree/trace_node.rb +33 -0
- data/lib/sass/tree/variable_node.rb +10 -4
- data/lib/sass/tree/visitors/base.rb +5 -8
- data/lib/sass/tree/visitors/check_nesting.rb +67 -52
- data/lib/sass/tree/visitors/convert.rb +134 -53
- data/lib/sass/tree/visitors/cssize.rb +245 -51
- data/lib/sass/tree/visitors/deep_copy.rb +102 -0
- data/lib/sass/tree/visitors/extend.rb +68 -0
- data/lib/sass/tree/visitors/perform.rb +331 -105
- data/lib/sass/tree/visitors/set_options.rb +125 -0
- data/lib/sass/tree/visitors/to_css.rb +259 -95
- data/lib/sass/tree/warn_node.rb +3 -3
- data/lib/sass/tree/while_node.rb +3 -3
- data/lib/sass/util/cross_platform_random.rb +19 -0
- data/lib/sass/util/multibyte_string_scanner.rb +157 -0
- data/lib/sass/util/normalized_map.rb +130 -0
- data/lib/sass/util/ordered_hash.rb +192 -0
- data/lib/sass/util/subset_map.rb +11 -2
- data/lib/sass/util/test.rb +9 -0
- data/lib/sass/util.rb +565 -39
- data/lib/sass/version.rb +27 -15
- data/lib/sass.rb +39 -4
- data/test/sass/cache_test.rb +15 -0
- data/test/sass/compiler_test.rb +223 -0
- data/test/sass/conversion_test.rb +901 -107
- data/test/sass/css2sass_test.rb +94 -0
- data/test/sass/engine_test.rb +1059 -164
- data/test/sass/exec_test.rb +86 -0
- data/test/sass/extend_test.rb +933 -837
- data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
- data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
- data/test/sass/functions_test.rb +995 -136
- data/test/sass/importer_test.rb +338 -18
- data/test/sass/logger_test.rb +58 -0
- data/test/sass/more_results/more_import.css +2 -2
- data/test/sass/plugin_test.rb +114 -30
- data/test/sass/results/cached_import_option.css +3 -0
- data/test/sass/results/filename_fn.css +3 -0
- data/test/sass/results/import.css +2 -2
- data/test/sass/results/import_charset.css +1 -0
- data/test/sass/results/import_charset_1_8.css +1 -0
- data/test/sass/results/import_charset_ibm866.css +1 -0
- data/test/sass/results/import_content.css +1 -0
- data/test/sass/results/script.css +1 -1
- data/test/sass/results/scss_import.css +2 -2
- data/test/sass/results/units.css +2 -2
- data/test/sass/script_conversion_test.rb +43 -1
- data/test/sass/script_test.rb +380 -36
- data/test/sass/scss/css_test.rb +257 -75
- data/test/sass/scss/scss_test.rb +2322 -110
- data/test/sass/source_map_test.rb +887 -0
- data/test/sass/templates/_cached_import_option_partial.scss +1 -0
- data/test/sass/templates/_double_import_loop2.sass +1 -0
- data/test/sass/templates/_filename_fn_import.scss +11 -0
- data/test/sass/templates/_imported_content.sass +3 -0
- data/test/sass/templates/_same_name_different_partiality.scss +1 -0
- data/test/sass/templates/bork5.sass +3 -0
- data/test/sass/templates/cached_import_option.scss +3 -0
- data/test/sass/templates/double_import_loop1.sass +1 -0
- data/test/sass/templates/filename_fn.scss +18 -0
- data/test/sass/templates/import_charset.sass +2 -0
- data/test/sass/templates/import_charset_1_8.sass +2 -0
- data/test/sass/templates/import_charset_ibm866.sass +2 -0
- data/test/sass/templates/import_content.sass +4 -0
- data/test/sass/templates/same_name_different_ext.sass +2 -0
- data/test/sass/templates/same_name_different_ext.scss +1 -0
- data/test/sass/templates/same_name_different_partiality.scss +1 -0
- data/test/sass/templates/single_import_loop.sass +1 -0
- data/test/sass/templates/subdir/import_up1.scss +1 -0
- data/test/sass/templates/subdir/import_up2.scss +1 -0
- data/test/sass/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
- data/test/sass/util/normalized_map_test.rb +51 -0
- data/test/sass/util_test.rb +183 -0
- data/test/sass/value_helpers_test.rb +181 -0
- data/test/test_helper.rb +45 -5
- data/vendor/listen/CHANGELOG.md +228 -0
- data/vendor/listen/CONTRIBUTING.md +38 -0
- data/vendor/listen/Gemfile +30 -0
- data/vendor/listen/Guardfile +8 -0
- data/vendor/{fssm → listen}/LICENSE +1 -1
- data/vendor/listen/README.md +315 -0
- data/vendor/listen/Rakefile +47 -0
- data/vendor/listen/Vagrantfile +96 -0
- data/vendor/listen/lib/listen/adapter.rb +214 -0
- data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
- data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
- data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
- data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
- data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
- data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
- data/vendor/listen/lib/listen/directory_record.rb +371 -0
- data/vendor/listen/lib/listen/listener.rb +225 -0
- data/vendor/listen/lib/listen/multi_listener.rb +143 -0
- data/vendor/listen/lib/listen/turnstile.rb +28 -0
- data/vendor/listen/lib/listen/version.rb +3 -0
- data/vendor/listen/lib/listen.rb +40 -0
- data/vendor/listen/listen.gemspec +22 -0
- data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
- data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
- data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
- data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
- data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
- data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
- data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
- data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
- data/vendor/listen/spec/listen/listener_spec.rb +169 -0
- data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
- data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
- data/vendor/listen/spec/listen_spec.rb +73 -0
- data/vendor/listen/spec/spec_helper.rb +21 -0
- data/vendor/listen/spec/support/adapter_helper.rb +629 -0
- data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
- data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
- data/vendor/listen/spec/support/listeners_helper.rb +156 -0
- data/vendor/listen/spec/support/platform_helper.rb +15 -0
- metadata +344 -271
- data/lib/sass/less.rb +0 -382
- data/lib/sass/script/bool.rb +0 -18
- data/lib/sass/script/funcall.rb +0 -162
- data/lib/sass/script/list.rb +0 -76
- data/lib/sass/script/literal.rb +0 -245
- data/lib/sass/script/variable.rb +0 -54
- data/lib/sass/scss/sass_parser.rb +0 -11
- data/test/sass/less_conversion_test.rb +0 -653
- data/vendor/fssm/README.markdown +0 -55
- data/vendor/fssm/Rakefile +0 -59
- data/vendor/fssm/VERSION.yml +0 -5
- data/vendor/fssm/example.rb +0 -9
- data/vendor/fssm/fssm.gemspec +0 -77
- data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
- data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
- data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
- data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
- data/vendor/fssm/lib/fssm/monitor.rb +0 -26
- data/vendor/fssm/lib/fssm/path.rb +0 -91
- data/vendor/fssm/lib/fssm/pathname.rb +0 -502
- data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
- data/vendor/fssm/lib/fssm/state/file.rb +0 -24
- data/vendor/fssm/lib/fssm/support.rb +0 -63
- data/vendor/fssm/lib/fssm/tree.rb +0 -176
- data/vendor/fssm/lib/fssm.rb +0 -33
- data/vendor/fssm/profile/prof-cache.rb +0 -40
- data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
- data/vendor/fssm/profile/prof-pathname.rb +0 -68
- data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
- data/vendor/fssm/profile/prof.html +0 -2379
- data/vendor/fssm/spec/path_spec.rb +0 -75
- data/vendor/fssm/spec/root/duck/quack.txt +0 -0
- data/vendor/fssm/spec/root/file.css +0 -0
- data/vendor/fssm/spec/root/file.rb +0 -0
- data/vendor/fssm/spec/root/file.yml +0 -0
- data/vendor/fssm/spec/root/moo/cow.txt +0 -0
- data/vendor/fssm/spec/spec_helper.rb +0 -14
data/lib/sass/exec.rb
CHANGED
@@ -17,6 +17,7 @@ module Sass
|
|
17
17
|
#
|
18
18
|
# @see #parse
|
19
19
|
def parse!
|
20
|
+
# rubocop:disable RescueException
|
20
21
|
begin
|
21
22
|
parse
|
22
23
|
rescue Exception => e
|
@@ -28,6 +29,7 @@ module Sass
|
|
28
29
|
exit 1
|
29
30
|
end
|
30
31
|
exit 0
|
32
|
+
# rubocop:enable RescueException
|
31
33
|
end
|
32
34
|
|
33
35
|
# Parses the command-line arguments and runs the executable.
|
@@ -58,7 +60,9 @@ module Sass
|
|
58
60
|
def get_line(exception)
|
59
61
|
# SyntaxErrors have weird line reporting
|
60
62
|
# when there's trailing whitespace
|
61
|
-
|
63
|
+
if exception.is_a?(::SyntaxError)
|
64
|
+
return (exception.message.scan(/:(\d+)/).first || ["??"]).first
|
65
|
+
end
|
62
66
|
(exception.backtrace[0].scan(/:(\d+)/).first || ["??"]).first
|
63
67
|
end
|
64
68
|
|
@@ -70,7 +74,8 @@ module Sass
|
|
70
74
|
#
|
71
75
|
# @param opts [OptionParser]
|
72
76
|
def set_opts(opts)
|
73
|
-
opts.on('-s', '--stdin', :NONE,
|
77
|
+
opts.on('-s', '--stdin', :NONE,
|
78
|
+
'Read input from standard input instead of an input file') do
|
74
79
|
@options[:input] = $stdin
|
75
80
|
end
|
76
81
|
|
@@ -95,6 +100,7 @@ module Sass
|
|
95
100
|
|
96
101
|
# Processes the options set by the command-line arguments.
|
97
102
|
# In particular, sets `@options[:input]` and `@options[:output]`
|
103
|
+
# (and `@options[:sourcemap]` if one has been specified)
|
98
104
|
# to appropriate IO streams.
|
99
105
|
#
|
100
106
|
# This is meant to be overridden by subclasses
|
@@ -108,12 +114,17 @@ module Sass
|
|
108
114
|
@options[:filename] = filename
|
109
115
|
open_file(filename) || $stdin
|
110
116
|
end
|
111
|
-
|
117
|
+
@options[:output_filename] = args.shift
|
118
|
+
output ||= @options[:output_filename] || $stdout
|
119
|
+
|
120
|
+
if @options[:sourcemap] && @options[:output_filename]
|
121
|
+
@options[:sourcemap_filename] = Util.sourcemap_name(@options[:output_filename])
|
122
|
+
end
|
112
123
|
|
113
124
|
@options[:input], @options[:output] = input, output
|
114
125
|
end
|
115
126
|
|
116
|
-
COLORS = {
|
127
|
+
COLORS = {:red => 31, :green => 32, :yellow => 33}
|
117
128
|
|
118
129
|
# Prints a status message about performing the given action,
|
119
130
|
# colored using the given color (via terminal escapes) if possible.
|
@@ -125,11 +136,12 @@ module Sass
|
|
125
136
|
def puts_action(name, color, arg)
|
126
137
|
return if @options[:for_engine][:quiet]
|
127
138
|
printf color(color, "%11s %s\n"), name, arg
|
139
|
+
STDOUT.flush
|
128
140
|
end
|
129
141
|
|
130
|
-
# Same as
|
142
|
+
# Same as `Kernel.puts`, but doesn't print anything if the `--quiet` option is set.
|
131
143
|
#
|
132
|
-
# @param args [Array] Passed on to
|
144
|
+
# @param args [Array] Passed on to `Kernel.puts`
|
133
145
|
def puts(*args)
|
134
146
|
return if @options[:for_engine][:quiet]
|
135
147
|
Kernel.puts(*args)
|
@@ -151,7 +163,15 @@ module Sass
|
|
151
163
|
# so we just filter for Windows terms (which don't set TERM)
|
152
164
|
# and not-real terminals, which aren't ttys.
|
153
165
|
return str if ENV["TERM"].nil? || ENV["TERM"].empty? || !STDOUT.tty?
|
154
|
-
|
166
|
+
"\e[#{COLORS[color]}m#{str}\e[0m"
|
167
|
+
end
|
168
|
+
|
169
|
+
def write_output(text, destination)
|
170
|
+
if destination.is_a?(String)
|
171
|
+
open_file(destination, 'w') {|file| file.write(text)}
|
172
|
+
else
|
173
|
+
destination.write(text)
|
174
|
+
end
|
155
175
|
end
|
156
176
|
|
157
177
|
private
|
@@ -159,7 +179,10 @@ module Sass
|
|
159
179
|
def open_file(filename, flag = 'r')
|
160
180
|
return if filename.nil?
|
161
181
|
flag = 'wb' if @options[:unix_newlines] && flag == 'w'
|
162
|
-
File.open(filename, flag)
|
182
|
+
file = File.open(filename, flag)
|
183
|
+
return file unless block_given?
|
184
|
+
yield file
|
185
|
+
file.close
|
163
186
|
end
|
164
187
|
|
165
188
|
def handle_load_error(err)
|
@@ -182,7 +205,7 @@ MESSAGE
|
|
182
205
|
def initialize(args)
|
183
206
|
super
|
184
207
|
@options[:for_engine] = {
|
185
|
-
:load_paths =>
|
208
|
+
:load_paths => default_sass_path
|
186
209
|
}
|
187
210
|
@default_syntax = :sass
|
188
211
|
end
|
@@ -192,6 +215,8 @@ MESSAGE
|
|
192
215
|
# Tells optparse how to parse the arguments.
|
193
216
|
#
|
194
217
|
# @param opts [OptionParser]
|
218
|
+
# @comment
|
219
|
+
# rubocop:disable MethodLength
|
195
220
|
def set_opts(opts)
|
196
221
|
super
|
197
222
|
|
@@ -229,15 +254,28 @@ END
|
|
229
254
|
'Only meaningful for --watch and --update.') do
|
230
255
|
@options[:stop_on_error] = true
|
231
256
|
end
|
257
|
+
opts.on('--poll', 'Check for file changes manually, rather than relying on the OS.',
|
258
|
+
'Only meaningful for --watch.') do
|
259
|
+
@options[:poll] = true
|
260
|
+
end
|
261
|
+
opts.on('-f', '--force', 'Recompile all Sass files, even if the CSS file is newer.',
|
262
|
+
'Only meaningful for --update.') do
|
263
|
+
@options[:force] = true
|
264
|
+
end
|
232
265
|
opts.on('-c', '--check', "Just check syntax, don't evaluate.") do
|
233
266
|
require 'stringio'
|
234
267
|
@options[:check_syntax] = true
|
235
268
|
@options[:output] = StringIO.new
|
236
269
|
end
|
237
|
-
|
238
|
-
|
270
|
+
style_desc = 'Output style. Can be nested (default), compact, compressed, or expanded.'
|
271
|
+
opts.on('-t', '--style NAME', style_desc) do |name|
|
239
272
|
@options[:for_engine][:style] = name.to_sym
|
240
273
|
end
|
274
|
+
opts.on('--precision NUMBER_OF_DIGITS', Integer,
|
275
|
+
"How many digits of precision to use when outputting decimal numbers." +
|
276
|
+
"Defaults to #{::Sass::Script::Value::Number.precision}.") do |precision|
|
277
|
+
::Sass::Script::Value::Number.precision = precision
|
278
|
+
end
|
241
279
|
opts.on('-q', '--quiet', 'Silence warnings and status messages during compilation.') do
|
242
280
|
@options[:for_engine][:quiet] = true
|
243
281
|
end
|
@@ -245,7 +283,7 @@ END
|
|
245
283
|
@options[:compass] = true
|
246
284
|
end
|
247
285
|
opts.on('-g', '--debug-info',
|
248
|
-
'Emit
|
286
|
+
'Emit output that can be used by the FireSass Firebug plugin.') do
|
249
287
|
@options[:for_engine][:debug_info] = true
|
250
288
|
end
|
251
289
|
opts.on('-l', '--line-numbers', '--line-comments',
|
@@ -262,19 +300,33 @@ END
|
|
262
300
|
opts.on('-r', '--require LIB', 'Require a Ruby library before running Sass.') do |lib|
|
263
301
|
require lib
|
264
302
|
end
|
265
|
-
opts.on('--cache-location PATH',
|
303
|
+
opts.on('--cache-location PATH',
|
304
|
+
'The path to put cached Sass files. Defaults to .sass-cache.') do |loc|
|
266
305
|
@options[:for_engine][:cache_location] = loc
|
267
306
|
end
|
268
307
|
opts.on('-C', '--no-cache', "Don't cache to sassc files.") do
|
269
308
|
@options[:for_engine][:cache] = false
|
270
309
|
end
|
310
|
+
opts.on('--sourcemap', 'Create sourcemap files next to the generated CSS files.') do
|
311
|
+
@options[:sourcemap] = true
|
312
|
+
end
|
271
313
|
|
272
|
-
|
273
|
-
|
314
|
+
encoding_desc = if ::Sass::Util.ruby1_8?
|
315
|
+
'Does not work in ruby 1.8.'
|
316
|
+
else
|
317
|
+
'Specify the default encoding for Sass files.'
|
318
|
+
end
|
319
|
+
opts.on('-E', '--default-encoding ENCODING', encoding_desc) do |encoding|
|
320
|
+
if ::Sass::Util.ruby1_8?
|
321
|
+
$stderr.puts "Specifying the encoding is not supported in ruby 1.8."
|
322
|
+
exit 1
|
323
|
+
else
|
274
324
|
Encoding.default_external = encoding
|
275
325
|
end
|
276
326
|
end
|
277
327
|
end
|
328
|
+
# @comment
|
329
|
+
# rubocop:enable MethodLength
|
278
330
|
|
279
331
|
# Processes the options set by the command-line arguments,
|
280
332
|
# and runs the Sass compiler appropriately.
|
@@ -294,6 +346,8 @@ END
|
|
294
346
|
return watch_or_update if @options[:watch] || @options[:update]
|
295
347
|
super
|
296
348
|
@options[:for_engine][:filename] = @options[:filename]
|
349
|
+
@options[:for_engine][:css_filename] = @options[:output] if @options[:output].is_a?(String)
|
350
|
+
@options[:for_engine][:sourcemap_filename] = @options[:sourcemap_filename]
|
297
351
|
|
298
352
|
begin
|
299
353
|
input = @options[:input]
|
@@ -308,16 +362,32 @@ END
|
|
308
362
|
# We don't need to do any special handling of @options[:check_syntax] here,
|
309
363
|
# because the Sass syntax checking happens alongside evaluation
|
310
364
|
# and evaluation doesn't actually evaluate any code anyway.
|
311
|
-
::Sass::Engine.new(input.read
|
365
|
+
::Sass::Engine.new(input.read, @options[:for_engine])
|
312
366
|
end
|
313
367
|
|
314
|
-
input.close
|
368
|
+
input.close if input.is_a?(File)
|
369
|
+
|
370
|
+
if @options[:sourcemap]
|
371
|
+
unless @options[:sourcemap_filename]
|
372
|
+
raise "Can't generate a sourcemap for an input without a path."
|
373
|
+
end
|
315
374
|
|
316
|
-
|
317
|
-
|
375
|
+
relative_sourcemap_path = ::Sass::Util.pathname(@options[:sourcemap_filename]).
|
376
|
+
relative_path_from(::Sass::Util.pathname(@options[:output_filename]).dirname)
|
377
|
+
rendered, mapping = engine.render_with_sourcemap(relative_sourcemap_path.to_s)
|
378
|
+
write_output(rendered, output)
|
379
|
+
write_output(mapping.to_json(
|
380
|
+
:css_path => @options[:output_filename],
|
381
|
+
:sourcemap_path => @options[:sourcemap_filename]) + "\n",
|
382
|
+
@options[:sourcemap_filename])
|
383
|
+
else
|
384
|
+
write_output(engine.render, output)
|
385
|
+
end
|
318
386
|
rescue ::Sass::SyntaxError => e
|
319
387
|
raise e if @options[:trace]
|
320
388
|
raise e.sass_backtrace_str("standard input")
|
389
|
+
ensure
|
390
|
+
output.close if output.is_a? File
|
321
391
|
end
|
322
392
|
end
|
323
393
|
|
@@ -345,10 +415,19 @@ END
|
|
345
415
|
::Sass::Repl.new(@options).run
|
346
416
|
end
|
347
417
|
|
418
|
+
# @comment
|
419
|
+
# rubocop:disable MethodLength
|
348
420
|
def watch_or_update
|
349
421
|
require 'sass/plugin'
|
350
422
|
::Sass::Plugin.options.merge! @options[:for_engine]
|
351
423
|
::Sass::Plugin.options[:unix_newlines] = @options[:unix_newlines]
|
424
|
+
::Sass::Plugin.options[:poll] = @options[:poll]
|
425
|
+
::Sass::Plugin.options[:sourcemap] = @options[:sourcemap]
|
426
|
+
|
427
|
+
if @options[:force]
|
428
|
+
raise "The --force flag may only be used with --update." unless @options[:update]
|
429
|
+
::Sass::Plugin.options[:always_update] = true
|
430
|
+
end
|
352
431
|
|
353
432
|
raise <<MSG if @args.empty?
|
354
433
|
What files should I watch? Did you mean something like:
|
@@ -372,25 +451,38 @@ MSG
|
|
372
451
|
|
373
452
|
dirs, files = @args.map {|name| split_colon_path(name)}.
|
374
453
|
partition {|i, _| File.directory? i}
|
375
|
-
files.map!
|
454
|
+
files.map! do |from, to|
|
455
|
+
to ||= from.gsub(/\.[^.]*?$/, '.css')
|
456
|
+
sourcemap = Util.sourcemap_name(to) if @options[:sourcemap]
|
457
|
+
[from, to, sourcemap]
|
458
|
+
end
|
376
459
|
dirs.map! {|from, to| [from, to || from]}
|
377
460
|
::Sass::Plugin.options[:template_location] = dirs
|
378
461
|
|
379
|
-
::Sass::Plugin.
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
puts_action :create, :green, css
|
462
|
+
::Sass::Plugin.on_updated_stylesheet do |_, css, sourcemap|
|
463
|
+
[css, sourcemap].each do |file|
|
464
|
+
next unless file
|
465
|
+
puts_action :write, :green, file
|
384
466
|
end
|
385
467
|
end
|
386
468
|
|
387
469
|
had_error = false
|
388
470
|
::Sass::Plugin.on_creating_directory {|dirname| puts_action :directory, :green, dirname}
|
389
471
|
::Sass::Plugin.on_deleting_css {|filename| puts_action :delete, :yellow, filename}
|
472
|
+
::Sass::Plugin.on_deleting_sourcemap {|filename| puts_action :delete, :yellow, filename}
|
390
473
|
::Sass::Plugin.on_compilation_error do |error, _, _|
|
474
|
+
if error.is_a?(SystemCallError) && !@options[:stop_on_error]
|
475
|
+
had_error = true
|
476
|
+
puts_action :error, :red, error.message
|
477
|
+
STDOUT.flush
|
478
|
+
next
|
479
|
+
end
|
480
|
+
|
391
481
|
raise error unless error.is_a?(::Sass::SyntaxError) && !@options[:stop_on_error]
|
392
482
|
had_error = true
|
393
|
-
puts_action :error, :red,
|
483
|
+
puts_action :error, :red,
|
484
|
+
"#{error.sass_filename} (Line #{error.sass_line}: #{error.message})"
|
485
|
+
STDOUT.flush
|
394
486
|
end
|
395
487
|
|
396
488
|
if @options[:update]
|
@@ -401,12 +493,23 @@ MSG
|
|
401
493
|
|
402
494
|
puts ">>> Sass is watching for changes. Press Ctrl-C to stop."
|
403
495
|
|
404
|
-
::Sass::Plugin.on_template_modified
|
405
|
-
|
406
|
-
|
496
|
+
::Sass::Plugin.on_template_modified do |template|
|
497
|
+
puts ">>> Change detected to: #{template}"
|
498
|
+
STDOUT.flush
|
499
|
+
end
|
500
|
+
::Sass::Plugin.on_template_created do |template|
|
501
|
+
puts ">>> New template detected: #{template}"
|
502
|
+
STDOUT.flush
|
503
|
+
end
|
504
|
+
::Sass::Plugin.on_template_deleted do |template|
|
505
|
+
puts ">>> Deleted template detected: #{template}"
|
506
|
+
STDOUT.flush
|
507
|
+
end
|
407
508
|
|
408
509
|
::Sass::Plugin.watch(files)
|
409
510
|
end
|
511
|
+
# @comment
|
512
|
+
# rubocop:enable MethodLength
|
410
513
|
|
411
514
|
def colon_path?(path)
|
412
515
|
!split_colon_path(path)[1].nil?
|
@@ -429,7 +532,17 @@ MSG
|
|
429
532
|
def probably_dest_dir?(path)
|
430
533
|
return false unless path
|
431
534
|
return false if colon_path?(path)
|
432
|
-
|
535
|
+
::Sass::Util.glob(File.join(path, "*.s[ca]ss")).empty?
|
536
|
+
end
|
537
|
+
|
538
|
+
def default_sass_path
|
539
|
+
if ENV['SASS_PATH']
|
540
|
+
# The select here prevents errors when the environment's
|
541
|
+
# load paths specified do not exist.
|
542
|
+
ENV['SASS_PATH'].split(File::PATH_SEPARATOR).select {|d| File.directory?(d)}
|
543
|
+
else
|
544
|
+
[::Sass::Importers::DeprecatedPath.new(".")]
|
545
|
+
end
|
433
546
|
end
|
434
547
|
end
|
435
548
|
|
@@ -454,6 +567,8 @@ MSG
|
|
454
567
|
# Tells optparse how to parse the arguments.
|
455
568
|
#
|
456
569
|
# @param opts [OptionParser]
|
570
|
+
# @comment
|
571
|
+
# rubocop:disable MethodLength
|
457
572
|
def set_opts(opts)
|
458
573
|
opts.banner = <<END
|
459
574
|
Usage: sass-convert [options] [INPUT] [OUTPUT]
|
@@ -467,14 +582,14 @@ Options:
|
|
467
582
|
END
|
468
583
|
|
469
584
|
opts.on('-F', '--from FORMAT',
|
470
|
-
'The format to convert from. Can be css, scss, sass
|
585
|
+
'The format to convert from. Can be css, scss, sass.',
|
471
586
|
'By default, this is inferred from the input filename.',
|
472
587
|
'If there is none, defaults to css.') do |name|
|
473
588
|
@options[:from] = name.downcase.to_sym
|
474
|
-
|
589
|
+
raise "sass-convert no longer supports LessCSS." if @options[:from] == :less
|
590
|
+
unless [:css, :scss, :sass].include?(@options[:from])
|
475
591
|
raise "Unknown format for sass-convert --from: #{name}"
|
476
592
|
end
|
477
|
-
try_less_note if @options[:from] == :less
|
478
593
|
end
|
479
594
|
|
480
595
|
opts.on('-T', '--to FORMAT',
|
@@ -502,6 +617,17 @@ END
|
|
502
617
|
@options[:for_tree][:dasherize] = true
|
503
618
|
end
|
504
619
|
|
620
|
+
opts.on('--indent NUM',
|
621
|
+
'How many spaces to use for each level of indentation. Defaults to 2.',
|
622
|
+
'"t" means use hard tabs.') do |indent|
|
623
|
+
|
624
|
+
if indent == 't'
|
625
|
+
@options[:for_tree][:indent] = "\t"
|
626
|
+
else
|
627
|
+
@options[:for_tree][:indent] = " " * indent.to_i
|
628
|
+
end
|
629
|
+
end
|
630
|
+
|
505
631
|
opts.on('--old', 'Output the old-style ":prop val" property syntax.',
|
506
632
|
'Only meaningful when generating Sass.') do
|
507
633
|
@options[:for_tree][:old] = true
|
@@ -512,13 +638,16 @@ END
|
|
512
638
|
end
|
513
639
|
|
514
640
|
unless ::Sass::Util.ruby1_8?
|
515
|
-
opts.on('-E encoding',
|
641
|
+
opts.on('-E encoding',
|
642
|
+
'Specify the default encoding for Sass and CSS files.') do |encoding|
|
516
643
|
Encoding.default_external = encoding
|
517
644
|
end
|
518
645
|
end
|
519
646
|
|
520
647
|
super
|
521
648
|
end
|
649
|
+
# @comment
|
650
|
+
# rubocop:enable MethodLength
|
522
651
|
|
523
652
|
# Processes the options set by the command-line arguments,
|
524
653
|
# and runs the CSS compiler appropriately.
|
@@ -532,7 +661,9 @@ END
|
|
532
661
|
|
533
662
|
super
|
534
663
|
input = @options[:input]
|
535
|
-
|
664
|
+
if File.directory?(input)
|
665
|
+
raise "Error: '#{input.path}' is a directory (did you mean to use --recursive?)"
|
666
|
+
end
|
536
667
|
output = @options[:output]
|
537
668
|
output = input if @options[:in_place]
|
538
669
|
process_file(input, output)
|
@@ -541,27 +672,29 @@ END
|
|
541
672
|
private
|
542
673
|
|
543
674
|
def process_directory
|
544
|
-
unless input = @options[:input] = @args.shift
|
675
|
+
unless (input = @options[:input] = @args.shift)
|
545
676
|
raise "Error: directory required when using --recursive."
|
546
677
|
end
|
547
678
|
|
548
679
|
output = @options[:output] = @args.shift
|
549
680
|
raise "Error: --from required when using --recursive." unless @options[:from]
|
550
681
|
raise "Error: --to required when using --recursive." unless @options[:to]
|
551
|
-
|
552
|
-
|
682
|
+
unless File.directory?(@options[:input])
|
683
|
+
raise "Error: '#{@options[:input]}' is not a directory"
|
684
|
+
end
|
685
|
+
if @options[:output] && File.exists?(@options[:output]) &&
|
686
|
+
!File.directory?(@options[:output])
|
553
687
|
raise "Error: '#{@options[:output]}' is not a directory"
|
554
688
|
end
|
555
689
|
@options[:output] ||= @options[:input]
|
556
690
|
|
557
|
-
from = @options[:from]
|
558
691
|
if @options[:to] == @options[:from] && !@options[:in_place]
|
559
692
|
fmt = @options[:from]
|
560
693
|
raise "Error: converting from #{fmt} to #{fmt} without --in-place"
|
561
694
|
end
|
562
695
|
|
563
696
|
ext = @options[:from]
|
564
|
-
|
697
|
+
::Sass::Util.glob("#{@options[:input]}/**/*.#{ext}") do |f|
|
565
698
|
output =
|
566
699
|
if @options[:in_place]
|
567
700
|
f
|
@@ -585,7 +718,6 @@ END
|
|
585
718
|
end
|
586
719
|
|
587
720
|
input = open_file(f)
|
588
|
-
output = @options[:in_place] ? input : open_file(output, "w")
|
589
721
|
process_file(input, output)
|
590
722
|
end
|
591
723
|
end
|
@@ -596,7 +728,7 @@ END
|
|
596
728
|
case input.path
|
597
729
|
when /\.scss$/; :scss
|
598
730
|
when /\.sass$/; :sass
|
599
|
-
when /\.less$/;
|
731
|
+
when /\.less$/; raise "sass-convert no longer supports LessCSS."
|
600
732
|
when /\.css$/; :css
|
601
733
|
end
|
602
734
|
elsif @options[:in_place]
|
@@ -620,11 +752,6 @@ END
|
|
620
752
|
if @options[:from] == :css
|
621
753
|
require 'sass/css'
|
622
754
|
::Sass::CSS.new(input.read, @options[:for_tree]).render(@options[:to])
|
623
|
-
elsif @options[:from] == :less
|
624
|
-
require 'sass/less'
|
625
|
-
try_less_note
|
626
|
-
input = input.read if input.is_a?(IO) && !input.is_a?(File) # Less is dumb
|
627
|
-
Less::Engine.new(input).to_tree.to_sass_tree.send("to_#{@options[:to]}", @options[:for_tree])
|
628
755
|
else
|
629
756
|
if input.is_a?(File)
|
630
757
|
::Sass::Engine.for_file(input.path, @options[:for_engine])
|
@@ -634,8 +761,8 @@ END
|
|
634
761
|
end
|
635
762
|
end
|
636
763
|
|
637
|
-
output =
|
638
|
-
|
764
|
+
output = input.path if @options[:in_place]
|
765
|
+
write_output(out, output)
|
639
766
|
rescue ::Sass::SyntaxError => e
|
640
767
|
raise e if @options[:trace]
|
641
768
|
file = " of #{e.sass_filename}" if e.sass_filename
|
@@ -643,17 +770,6 @@ END
|
|
643
770
|
rescue LoadError => err
|
644
771
|
handle_load_error(err)
|
645
772
|
end
|
646
|
-
|
647
|
-
@@less_note_printed = false
|
648
|
-
def try_less_note
|
649
|
-
return if @@less_note_printed
|
650
|
-
@@less_note_printed = true
|
651
|
-
warn <<NOTE
|
652
|
-
* NOTE: Sass and Less are different languages, and they work differently.
|
653
|
-
* I'll do my best to translate, but some features -- especially mixins --
|
654
|
-
* should be checked by hand.
|
655
|
-
NOTE
|
656
|
-
end
|
657
773
|
end
|
658
774
|
end
|
659
775
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'set'
|
2
|
+
module Sass
|
3
|
+
# Provides `Sass.has_feature?` which allows for simple feature detection
|
4
|
+
# by providing a feature name.
|
5
|
+
module Features
|
6
|
+
# This is the set of features that can be detected.
|
7
|
+
KNOWN_FEATURES = Set[*%w{
|
8
|
+
}]
|
9
|
+
|
10
|
+
# Check if a feature exists by name. This is used to implement
|
11
|
+
# the Sass function `feature-exists($feature)`
|
12
|
+
#
|
13
|
+
# @param feature_name [String] The case sensitive name of the feature to
|
14
|
+
# check if it exists in this version of Sass.
|
15
|
+
# @return [Boolean] whether the feature of that name exists.
|
16
|
+
def has_feature?(feature_name)
|
17
|
+
KNOWN_FEATURES.include?(feature_name)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Add a feature to Sass. Plugins can use this to easily expose their
|
21
|
+
# availability to end users. Plugins must prefix their feature
|
22
|
+
# names with a dash to distinguish them from official features.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# Sass.add_feature("-import-globbing")
|
26
|
+
# Sass.add_feature("-math-cos")
|
27
|
+
#
|
28
|
+
#
|
29
|
+
# @param feature_name [String] The case sensitive name of the feature to
|
30
|
+
# to add to Sass. Must begin with a dash.
|
31
|
+
def add_feature(feature_name)
|
32
|
+
unless feature_name[0] == ?-
|
33
|
+
raise ArgumentError.new("Plugin feature names must begin with a dash")
|
34
|
+
end
|
35
|
+
KNOWN_FEATURES << feature_name
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
extend Features
|
40
|
+
end
|
data/lib/sass/importers/base.rb
CHANGED
@@ -15,13 +15,9 @@ module Sass
|
|
15
15
|
# They should also implement the \{#find\_relative} method.
|
16
16
|
#
|
17
17
|
# Importers should be serializable via `Marshal.dump`.
|
18
|
-
# In addition to the standard `_dump` and `_load` methods,
|
19
|
-
# importers can define `_before_dump`, `_after_dump`, `_around_dump`,
|
20
|
-
# and `_after_load` methods as per {Sass::Util#dump} and {Sass::Util#load}.
|
21
18
|
#
|
22
19
|
# @abstract
|
23
20
|
class Base
|
24
|
-
|
25
21
|
# Find a Sass file relative to another file.
|
26
22
|
# Importers without a notion of "relative paths"
|
27
23
|
# should just return nil here.
|
@@ -72,7 +68,8 @@ module Sass
|
|
72
68
|
# If no such files exist, it should return nil.
|
73
69
|
#
|
74
70
|
# The {Sass::Engine} to be returned should be passed `options`,
|
75
|
-
# with a few modifications. `:
|
71
|
+
# with a few modifications. `:syntax` should be set appropriately,
|
72
|
+
# `:filename` should be set to `uri`,
|
76
73
|
# and `:importer` should be set to this importer.
|
77
74
|
#
|
78
75
|
# @param uri [String] The URI to import.
|
@@ -121,6 +118,29 @@ module Sass
|
|
121
118
|
Sass::Util.abstract(self)
|
122
119
|
end
|
123
120
|
|
121
|
+
# Get the publicly-visible URL for an imported file. This URL is used by
|
122
|
+
# source maps to link to the source stylesheet. This may return `nil` to
|
123
|
+
# indicate that no public URL is available; however, this will cause
|
124
|
+
# sourcemap generation to fail if any CSS is generated from files imported
|
125
|
+
# from this importer.
|
126
|
+
#
|
127
|
+
# @param uri [String] A URI known to be valid for this importer.
|
128
|
+
# @param sourcemap_directory [String, NilClass] The absolute path to a
|
129
|
+
# directory on disk where the sourcemap will be saved. If uri refers to
|
130
|
+
# a file on disk that's accessible relative to sourcemap_directory, this
|
131
|
+
# may return a relative URL. This may be `nil` if the sourcemap's
|
132
|
+
# eventual location is unknown.
|
133
|
+
# @return [String?] The publicly-visible URL for this file, or `nil`
|
134
|
+
# indicating that no publicly-visible URL exists.
|
135
|
+
def public_url(uri, sourcemap_directory = nil)
|
136
|
+
return if @public_url_warning_issued
|
137
|
+
@public_url_warning_issued = true
|
138
|
+
Sass::Util.sass_warn <<WARNING
|
139
|
+
WARNING: #{self.class.name} should define the #public_url method.
|
140
|
+
WARNING
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
|
124
144
|
# A string representation of the importer.
|
125
145
|
# Should be overridden by subclasses.
|
126
146
|
#
|
@@ -131,8 +151,27 @@ module Sass
|
|
131
151
|
def to_s
|
132
152
|
Sass::Util.abstract(self)
|
133
153
|
end
|
154
|
+
|
155
|
+
# If the importer is based on files on the local filesystem
|
156
|
+
# this method should return folders which should be watched
|
157
|
+
# for changes.
|
158
|
+
#
|
159
|
+
# @return [Array<String>] List of absolute paths of directories to watch
|
160
|
+
def directories_to_watch
|
161
|
+
[]
|
162
|
+
end
|
163
|
+
|
164
|
+
# If this importer is based on files on the local filesystem This method
|
165
|
+
# should return true if the file, when changed, should trigger a
|
166
|
+
# recompile.
|
167
|
+
#
|
168
|
+
# It is acceptable for non-sass files to be watched and trigger a recompile.
|
169
|
+
#
|
170
|
+
# @param filename [String] The absolute filename for a file that has changed.
|
171
|
+
# @return [Boolean] When the file changed should cause a recompile.
|
172
|
+
def watched_file?(filename)
|
173
|
+
false
|
174
|
+
end
|
134
175
|
end
|
135
176
|
end
|
136
177
|
end
|
137
|
-
|
138
|
-
|