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/environment.rb
CHANGED
|
@@ -1,60 +1,20 @@
|
|
|
1
1
|
require 'set'
|
|
2
2
|
|
|
3
3
|
module Sass
|
|
4
|
-
# The lexical
|
|
5
|
-
|
|
6
|
-
#
|
|
7
|
-
# A new environment is created for each level of Sass nesting.
|
|
8
|
-
# This allows variables to be lexically scoped.
|
|
9
|
-
# The new environment refers to the environment in the upper scope,
|
|
10
|
-
# so it has access to variables defined in enclosing scopes,
|
|
11
|
-
# but new variables are defined locally.
|
|
12
|
-
#
|
|
13
|
-
# Environment also keeps track of the {Engine} options
|
|
14
|
-
# so that they can be made available to {Sass::Script::Functions}.
|
|
15
|
-
class Environment
|
|
16
|
-
# The enclosing environment,
|
|
17
|
-
# or nil if this is the global environment.
|
|
18
|
-
#
|
|
19
|
-
# @return [Environment]
|
|
20
|
-
attr_reader :parent
|
|
21
|
-
attr_reader :options
|
|
22
|
-
attr_writer :caller
|
|
23
|
-
attr_writer :content
|
|
24
|
-
|
|
25
|
-
# @param options [{Symbol => Object}] The options hash. See
|
|
26
|
-
# {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
|
|
27
|
-
# @param parent [Environment] See \{#parent}
|
|
28
|
-
def initialize(parent = nil, options = nil)
|
|
29
|
-
@parent = parent
|
|
30
|
-
@options = options || (parent && parent.options) || {}
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# The environment of the caller of this environment's mixin or function.
|
|
34
|
-
# @return {Environment?}
|
|
35
|
-
def caller
|
|
36
|
-
@caller || (@parent && @parent.caller)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# The content passed to this environmnet. This is naturally only set
|
|
40
|
-
# for mixin body environments with content passed in.
|
|
41
|
-
# @return {Environment?}
|
|
42
|
-
def content
|
|
43
|
-
@content || (@parent && @parent.content)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
private
|
|
47
|
-
|
|
4
|
+
# The abstract base class for lexical environments for SassScript.
|
|
5
|
+
class BaseEnvironment
|
|
48
6
|
class << self
|
|
49
|
-
private
|
|
50
|
-
UNDERSCORE, DASH = '_', '-'
|
|
51
|
-
|
|
52
7
|
# Note: when updating this,
|
|
53
8
|
# update sass/yard/inherited_hash.rb as well.
|
|
54
|
-
def
|
|
55
|
-
|
|
9
|
+
def inherited_hash_accessor(name)
|
|
10
|
+
inherited_hash_reader(name)
|
|
11
|
+
inherited_hash_writer(name)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def inherited_hash_reader(name)
|
|
15
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
56
16
|
def #{name}(name)
|
|
57
|
-
_#{name}(name.tr(
|
|
17
|
+
_#{name}(name.tr('_', '-'))
|
|
58
18
|
end
|
|
59
19
|
|
|
60
20
|
def _#{name}(name)
|
|
@@ -62,8 +22,17 @@ module Sass
|
|
|
62
22
|
end
|
|
63
23
|
protected :_#{name}
|
|
64
24
|
|
|
25
|
+
def is_#{name}_global?(name)
|
|
26
|
+
return !@parent if @#{name}s && @#{name}s.has_key?(name)
|
|
27
|
+
@parent && @parent.is_#{name}_global?(name)
|
|
28
|
+
end
|
|
29
|
+
RUBY
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def inherited_hash_writer(name)
|
|
33
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
65
34
|
def set_#{name}(name, value)
|
|
66
|
-
name = name.tr(
|
|
35
|
+
name = name.tr('_', '-')
|
|
67
36
|
@#{name}s[name] = value unless try_set_#{name}(name, value)
|
|
68
37
|
end
|
|
69
38
|
|
|
@@ -82,20 +51,130 @@ module Sass
|
|
|
82
51
|
|
|
83
52
|
def set_local_#{name}(name, value)
|
|
84
53
|
@#{name}s ||= {}
|
|
85
|
-
@#{name}s[name.tr(
|
|
54
|
+
@#{name}s[name.tr('_', '-')] = value
|
|
86
55
|
end
|
|
87
|
-
RUBY
|
|
56
|
+
RUBY
|
|
88
57
|
end
|
|
89
58
|
end
|
|
90
59
|
|
|
60
|
+
# The options passed to the Sass Engine.
|
|
61
|
+
attr_reader :options
|
|
62
|
+
|
|
63
|
+
attr_writer :caller
|
|
64
|
+
attr_writer :content
|
|
65
|
+
attr_writer :selector
|
|
66
|
+
|
|
91
67
|
# variable
|
|
92
|
-
# Script::
|
|
93
|
-
|
|
68
|
+
# Script::Value
|
|
69
|
+
inherited_hash_reader :var
|
|
70
|
+
|
|
94
71
|
# mixin
|
|
95
72
|
# Sass::Callable
|
|
96
|
-
|
|
73
|
+
inherited_hash_reader :mixin
|
|
74
|
+
|
|
97
75
|
# function
|
|
98
76
|
# Sass::Callable
|
|
99
|
-
|
|
77
|
+
inherited_hash_reader :function
|
|
78
|
+
|
|
79
|
+
# @param options [{Symbol => Object}] The options hash. See
|
|
80
|
+
# {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
|
|
81
|
+
# @param parent [Environment] See \{#parent}
|
|
82
|
+
def initialize(parent = nil, options = nil)
|
|
83
|
+
@parent = parent
|
|
84
|
+
@options = options || (parent && parent.options) || {}
|
|
85
|
+
@stack = Sass::Stack.new if @parent.nil?
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# The environment of the caller of this environment's mixin or function.
|
|
89
|
+
# @return {Environment?}
|
|
90
|
+
def caller
|
|
91
|
+
@caller || (@parent && @parent.caller)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# The content passed to this environment. This is naturally only set
|
|
95
|
+
# for mixin body environments with content passed in.
|
|
96
|
+
#
|
|
97
|
+
# @return {[Array<Sass::Tree::Node>, Environment]?} The content nodes and
|
|
98
|
+
# the lexical environment of the content block.
|
|
99
|
+
def content
|
|
100
|
+
@content || (@parent && @parent.content)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# The selector for the current CSS rule, or nil if there is no
|
|
104
|
+
# current CSS rule.
|
|
105
|
+
#
|
|
106
|
+
# @return [Selector::CommaSequence?] The current selector, with any
|
|
107
|
+
# nesting fully resolved.
|
|
108
|
+
def selector
|
|
109
|
+
@selector || (@caller && @caller.selector) || (@parent && @parent.selector)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# The top-level Environment object.
|
|
113
|
+
#
|
|
114
|
+
# @return [Environment]
|
|
115
|
+
def global_env
|
|
116
|
+
@global_env ||= @parent.nil? ? self : @parent.global_env
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# The import/mixin stack.
|
|
120
|
+
#
|
|
121
|
+
# @return [Sass::Stack]
|
|
122
|
+
def stack
|
|
123
|
+
@stack || global_env.stack
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# The lexical environment for SassScript.
|
|
128
|
+
# This keeps track of variable, mixin, and function definitions.
|
|
129
|
+
#
|
|
130
|
+
# A new environment is created for each level of Sass nesting.
|
|
131
|
+
# This allows variables to be lexically scoped.
|
|
132
|
+
# The new environment refers to the environment in the upper scope,
|
|
133
|
+
# so it has access to variables defined in enclosing scopes,
|
|
134
|
+
# but new variables are defined locally.
|
|
135
|
+
#
|
|
136
|
+
# Environment also keeps track of the {Engine} options
|
|
137
|
+
# so that they can be made available to {Sass::Script::Functions}.
|
|
138
|
+
class Environment < BaseEnvironment
|
|
139
|
+
# The enclosing environment,
|
|
140
|
+
# or nil if this is the global environment.
|
|
141
|
+
#
|
|
142
|
+
# @return [Environment]
|
|
143
|
+
attr_reader :parent
|
|
144
|
+
|
|
145
|
+
# variable
|
|
146
|
+
# Script::Value
|
|
147
|
+
inherited_hash_writer :var
|
|
148
|
+
|
|
149
|
+
# mixin
|
|
150
|
+
# Sass::Callable
|
|
151
|
+
inherited_hash_writer :mixin
|
|
152
|
+
|
|
153
|
+
# function
|
|
154
|
+
# Sass::Callable
|
|
155
|
+
inherited_hash_writer :function
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# A read-only wrapper for a lexical environment for SassScript.
|
|
159
|
+
class ReadOnlyEnvironment < BaseEnvironment
|
|
160
|
+
# The read-only environment of the caller of this environment's mixin or function.
|
|
161
|
+
#
|
|
162
|
+
# @see BaseEnvironment#caller
|
|
163
|
+
# @return {ReadOnlyEnvironment}
|
|
164
|
+
def caller
|
|
165
|
+
return @caller if @caller
|
|
166
|
+
env = super
|
|
167
|
+
@caller ||= env.is_a?(ReadOnlyEnvironment) ? env : ReadOnlyEnvironment.new(env, env.options)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# The read-only content passed to this environment.
|
|
171
|
+
#
|
|
172
|
+
# @see BaseEnvironment#content
|
|
173
|
+
# @return {ReadOnlyEnvironment}
|
|
174
|
+
def content
|
|
175
|
+
return @content if @content
|
|
176
|
+
env = super
|
|
177
|
+
@content ||= env.is_a?(ReadOnlyEnvironment) ? env : ReadOnlyEnvironment.new(env, env.options)
|
|
178
|
+
end
|
|
100
179
|
end
|
|
101
180
|
end
|
data/lib/sass/error.rb
CHANGED
|
@@ -138,15 +138,15 @@ module Sass
|
|
|
138
138
|
# @see #sass_backtrace
|
|
139
139
|
# @return [String]
|
|
140
140
|
def sass_backtrace_str(default_filename = "an unknown file")
|
|
141
|
-
lines =
|
|
141
|
+
lines = message.split("\n")
|
|
142
142
|
msg = lines[0] + lines[1..-1].
|
|
143
143
|
map {|l| "\n" + (" " * "Syntax error: ".size) + l}.join
|
|
144
144
|
"Syntax error: #{msg}" +
|
|
145
145
|
Sass::Util.enum_with_index(sass_backtrace).map do |entry, i|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
"\n #{i == 0 ? "on" : "from"} line #{entry[:line]}" +
|
|
147
|
+
" of #{entry[:filename] || default_filename}" +
|
|
148
|
+
(entry[:mixin] ? ", in `#{entry[:mixin]}'" : "")
|
|
149
|
+
end.join
|
|
150
150
|
end
|
|
151
151
|
|
|
152
152
|
class << self
|
|
@@ -165,9 +165,9 @@ module Sass
|
|
|
165
165
|
|
|
166
166
|
<<END
|
|
167
167
|
/*
|
|
168
|
-
#{header}
|
|
168
|
+
#{header.gsub("*/", "*\\/")}
|
|
169
169
|
|
|
170
|
-
Backtrace:\n#{e.backtrace.join("\n")}
|
|
170
|
+
Backtrace:\n#{e.backtrace.join("\n").gsub("*/", "*\\/")}
|
|
171
171
|
*/
|
|
172
172
|
body:before {
|
|
173
173
|
white-space: pre;
|
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.
|
|
@@ -128,9 +139,9 @@ module Sass
|
|
|
128
139
|
STDOUT.flush
|
|
129
140
|
end
|
|
130
141
|
|
|
131
|
-
# Same as
|
|
142
|
+
# Same as `Kernel.puts`, but doesn't print anything if the `--quiet` option is set.
|
|
132
143
|
#
|
|
133
|
-
# @param args [Array] Passed on to
|
|
144
|
+
# @param args [Array] Passed on to `Kernel.puts`
|
|
134
145
|
def puts(*args)
|
|
135
146
|
return if @options[:for_engine][:quiet]
|
|
136
147
|
Kernel.puts(*args)
|
|
@@ -152,7 +163,15 @@ module Sass
|
|
|
152
163
|
# so we just filter for Windows terms (which don't set TERM)
|
|
153
164
|
# and not-real terminals, which aren't ttys.
|
|
154
165
|
return str if ENV["TERM"].nil? || ENV["TERM"].empty? || !STDOUT.tty?
|
|
155
|
-
|
|
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
|
|
156
175
|
end
|
|
157
176
|
|
|
158
177
|
private
|
|
@@ -160,7 +179,10 @@ module Sass
|
|
|
160
179
|
def open_file(filename, flag = 'r')
|
|
161
180
|
return if filename.nil?
|
|
162
181
|
flag = 'wb' if @options[:unix_newlines] && flag == 'w'
|
|
163
|
-
File.open(filename, flag)
|
|
182
|
+
file = File.open(filename, flag)
|
|
183
|
+
return file unless block_given?
|
|
184
|
+
yield file
|
|
185
|
+
file.close
|
|
164
186
|
end
|
|
165
187
|
|
|
166
188
|
def handle_load_error(err)
|
|
@@ -183,7 +205,7 @@ MESSAGE
|
|
|
183
205
|
def initialize(args)
|
|
184
206
|
super
|
|
185
207
|
@options[:for_engine] = {
|
|
186
|
-
:load_paths =>
|
|
208
|
+
:load_paths => default_sass_path
|
|
187
209
|
}
|
|
188
210
|
@default_syntax = :sass
|
|
189
211
|
end
|
|
@@ -193,6 +215,8 @@ MESSAGE
|
|
|
193
215
|
# Tells optparse how to parse the arguments.
|
|
194
216
|
#
|
|
195
217
|
# @param opts [OptionParser]
|
|
218
|
+
# @comment
|
|
219
|
+
# rubocop:disable MethodLength
|
|
196
220
|
def set_opts(opts)
|
|
197
221
|
super
|
|
198
222
|
|
|
@@ -243,13 +267,14 @@ END
|
|
|
243
267
|
@options[:check_syntax] = true
|
|
244
268
|
@options[:output] = StringIO.new
|
|
245
269
|
end
|
|
246
|
-
|
|
247
|
-
|
|
270
|
+
style_desc = 'Output style. Can be nested (default), compact, compressed, or expanded.'
|
|
271
|
+
opts.on('-t', '--style NAME', style_desc) do |name|
|
|
248
272
|
@options[:for_engine][:style] = name.to_sym
|
|
249
273
|
end
|
|
250
274
|
opts.on('--precision NUMBER_OF_DIGITS', Integer,
|
|
251
|
-
|
|
252
|
-
|
|
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
|
|
253
278
|
end
|
|
254
279
|
opts.on('-q', '--quiet', 'Silence warnings and status messages during compilation.') do
|
|
255
280
|
@options[:for_engine][:quiet] = true
|
|
@@ -258,7 +283,7 @@ END
|
|
|
258
283
|
@options[:compass] = true
|
|
259
284
|
end
|
|
260
285
|
opts.on('-g', '--debug-info',
|
|
261
|
-
'Emit
|
|
286
|
+
'Emit output that can be used by the FireSass Firebug plugin.') do
|
|
262
287
|
@options[:for_engine][:debug_info] = true
|
|
263
288
|
end
|
|
264
289
|
opts.on('-l', '--line-numbers', '--line-comments',
|
|
@@ -275,19 +300,33 @@ END
|
|
|
275
300
|
opts.on('-r', '--require LIB', 'Require a Ruby library before running Sass.') do |lib|
|
|
276
301
|
require lib
|
|
277
302
|
end
|
|
278
|
-
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|
|
|
279
305
|
@options[:for_engine][:cache_location] = loc
|
|
280
306
|
end
|
|
281
307
|
opts.on('-C', '--no-cache', "Don't cache to sassc files.") do
|
|
282
308
|
@options[:for_engine][:cache] = false
|
|
283
309
|
end
|
|
310
|
+
opts.on('--sourcemap', 'Create sourcemap files next to the generated CSS files.') do
|
|
311
|
+
@options[:sourcemap] = true
|
|
312
|
+
end
|
|
284
313
|
|
|
285
|
-
|
|
286
|
-
|
|
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 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
|
|
287
324
|
Encoding.default_external = encoding
|
|
288
325
|
end
|
|
289
326
|
end
|
|
290
327
|
end
|
|
328
|
+
# @comment
|
|
329
|
+
# rubocop:enable MethodLength
|
|
291
330
|
|
|
292
331
|
# Processes the options set by the command-line arguments,
|
|
293
332
|
# and runs the Sass compiler appropriately.
|
|
@@ -307,7 +346,7 @@ END
|
|
|
307
346
|
return watch_or_update if @options[:watch] || @options[:update]
|
|
308
347
|
super
|
|
309
348
|
@options[:for_engine][:filename] = @options[:filename]
|
|
310
|
-
@options[:for_engine][:css_filename] = @options[:output]
|
|
349
|
+
@options[:for_engine][:css_filename] = @options[:output] if @options[:output].is_a?(String)
|
|
311
350
|
|
|
312
351
|
begin
|
|
313
352
|
input = @options[:input]
|
|
@@ -322,16 +361,32 @@ END
|
|
|
322
361
|
# We don't need to do any special handling of @options[:check_syntax] here,
|
|
323
362
|
# because the Sass syntax checking happens alongside evaluation
|
|
324
363
|
# and evaluation doesn't actually evaluate any code anyway.
|
|
325
|
-
::Sass::Engine.new(input.read
|
|
364
|
+
::Sass::Engine.new(input.read, @options[:for_engine])
|
|
326
365
|
end
|
|
327
366
|
|
|
328
|
-
input.close
|
|
367
|
+
input.close if input.is_a?(File)
|
|
368
|
+
|
|
369
|
+
if @options[:sourcemap]
|
|
370
|
+
unless @options[:sourcemap_filename]
|
|
371
|
+
raise "Can't generate a sourcemap for an input without a path."
|
|
372
|
+
end
|
|
329
373
|
|
|
330
|
-
|
|
331
|
-
|
|
374
|
+
relative_sourcemap_path = Pathname.new(@options[:sourcemap_filename]).
|
|
375
|
+
relative_path_from(Pathname.new(@options[:output_filename]).dirname)
|
|
376
|
+
rendered, mapping = engine.render_with_sourcemap(relative_sourcemap_path.to_s)
|
|
377
|
+
write_output(rendered, output)
|
|
378
|
+
write_output(mapping.to_json(
|
|
379
|
+
:css_path => @options[:output_filename],
|
|
380
|
+
:sourcemap_path => @options[:sourcemap_filename]) + "\n",
|
|
381
|
+
@options[:sourcemap_filename])
|
|
382
|
+
else
|
|
383
|
+
write_output(engine.render, output)
|
|
384
|
+
end
|
|
332
385
|
rescue ::Sass::SyntaxError => e
|
|
333
386
|
raise e if @options[:trace]
|
|
334
387
|
raise e.sass_backtrace_str("standard input")
|
|
388
|
+
ensure
|
|
389
|
+
output.close if output.is_a? File
|
|
335
390
|
end
|
|
336
391
|
end
|
|
337
392
|
|
|
@@ -359,11 +414,14 @@ END
|
|
|
359
414
|
::Sass::Repl.new(@options).run
|
|
360
415
|
end
|
|
361
416
|
|
|
417
|
+
# @comment
|
|
418
|
+
# rubocop:disable MethodLength
|
|
362
419
|
def watch_or_update
|
|
363
420
|
require 'sass/plugin'
|
|
364
421
|
::Sass::Plugin.options.merge! @options[:for_engine]
|
|
365
422
|
::Sass::Plugin.options[:unix_newlines] = @options[:unix_newlines]
|
|
366
423
|
::Sass::Plugin.options[:poll] = @options[:poll]
|
|
424
|
+
::Sass::Plugin.options[:sourcemap] = @options[:sourcemap]
|
|
367
425
|
|
|
368
426
|
if @options[:force]
|
|
369
427
|
raise "The --force flag may only be used with --update." unless @options[:update]
|
|
@@ -392,21 +450,25 @@ MSG
|
|
|
392
450
|
|
|
393
451
|
dirs, files = @args.map {|name| split_colon_path(name)}.
|
|
394
452
|
partition {|i, _| File.directory? i}
|
|
395
|
-
files.map!
|
|
453
|
+
files.map! do |from, to|
|
|
454
|
+
to ||= from.gsub(/\.[^.]*?$/, '.css')
|
|
455
|
+
sourcemap = Util.sourcemap_name(to) if @options[:sourcemap]
|
|
456
|
+
[from, to, sourcemap]
|
|
457
|
+
end
|
|
396
458
|
dirs.map! {|from, to| [from, to || from]}
|
|
397
459
|
::Sass::Plugin.options[:template_location] = dirs
|
|
398
460
|
|
|
399
|
-
::Sass::Plugin.on_updated_stylesheet do |_, css|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
puts_action :create, :green, css
|
|
461
|
+
::Sass::Plugin.on_updated_stylesheet do |_, css, sourcemap|
|
|
462
|
+
[css, sourcemap].each do |file|
|
|
463
|
+
next unless file
|
|
464
|
+
puts_action :write, :green, file
|
|
404
465
|
end
|
|
405
466
|
end
|
|
406
467
|
|
|
407
468
|
had_error = false
|
|
408
469
|
::Sass::Plugin.on_creating_directory {|dirname| puts_action :directory, :green, dirname}
|
|
409
470
|
::Sass::Plugin.on_deleting_css {|filename| puts_action :delete, :yellow, filename}
|
|
471
|
+
::Sass::Plugin.on_deleting_sourcemap {|filename| puts_action :delete, :yellow, filename}
|
|
410
472
|
::Sass::Plugin.on_compilation_error do |error, _, _|
|
|
411
473
|
if error.is_a?(SystemCallError) && !@options[:stop_on_error]
|
|
412
474
|
had_error = true
|
|
@@ -417,7 +479,8 @@ MSG
|
|
|
417
479
|
|
|
418
480
|
raise error unless error.is_a?(::Sass::SyntaxError) && !@options[:stop_on_error]
|
|
419
481
|
had_error = true
|
|
420
|
-
puts_action :error, :red,
|
|
482
|
+
puts_action :error, :red,
|
|
483
|
+
"#{error.sass_filename} (Line #{error.sass_line}: #{error.message})"
|
|
421
484
|
STDOUT.flush
|
|
422
485
|
end
|
|
423
486
|
|
|
@@ -444,6 +507,8 @@ MSG
|
|
|
444
507
|
|
|
445
508
|
::Sass::Plugin.watch(files)
|
|
446
509
|
end
|
|
510
|
+
# @comment
|
|
511
|
+
# rubocop:enable MethodLength
|
|
447
512
|
|
|
448
513
|
def colon_path?(path)
|
|
449
514
|
!split_colon_path(path)[1].nil?
|
|
@@ -466,8 +531,19 @@ MSG
|
|
|
466
531
|
def probably_dest_dir?(path)
|
|
467
532
|
return false unless path
|
|
468
533
|
return false if colon_path?(path)
|
|
469
|
-
|
|
534
|
+
::Sass::Util.glob(File.join(path, "*.s[ca]ss")).empty?
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
def default_sass_path
|
|
538
|
+
if ENV['SASSPATH']
|
|
539
|
+
# The select here prevents errors when the environment's
|
|
540
|
+
# load paths specified do not exist.
|
|
541
|
+
ENV['SASSPATH'].split(File::PATH_SEPARATOR).select {|d| File.directory?(d)}
|
|
542
|
+
else
|
|
543
|
+
[::Sass::Importers::DeprecatedPath.new(".")]
|
|
544
|
+
end
|
|
470
545
|
end
|
|
546
|
+
|
|
471
547
|
end
|
|
472
548
|
|
|
473
549
|
class Scss < Sass
|
|
@@ -491,6 +567,8 @@ MSG
|
|
|
491
567
|
# Tells optparse how to parse the arguments.
|
|
492
568
|
#
|
|
493
569
|
# @param opts [OptionParser]
|
|
570
|
+
# @comment
|
|
571
|
+
# rubocop:disable MethodLength
|
|
494
572
|
def set_opts(opts)
|
|
495
573
|
opts.banner = <<END
|
|
496
574
|
Usage: sass-convert [options] [INPUT] [OUTPUT]
|
|
@@ -560,13 +638,16 @@ END
|
|
|
560
638
|
end
|
|
561
639
|
|
|
562
640
|
unless ::Sass::Util.ruby1_8?
|
|
563
|
-
opts.on('-E encoding',
|
|
641
|
+
opts.on('-E encoding',
|
|
642
|
+
'Specify the default encoding for Sass and CSS files.') do |encoding|
|
|
564
643
|
Encoding.default_external = encoding
|
|
565
644
|
end
|
|
566
645
|
end
|
|
567
646
|
|
|
568
647
|
super
|
|
569
648
|
end
|
|
649
|
+
# @comment
|
|
650
|
+
# rubocop:enable MethodLength
|
|
570
651
|
|
|
571
652
|
# Processes the options set by the command-line arguments,
|
|
572
653
|
# and runs the CSS compiler appropriately.
|
|
@@ -580,7 +661,9 @@ END
|
|
|
580
661
|
|
|
581
662
|
super
|
|
582
663
|
input = @options[:input]
|
|
583
|
-
|
|
664
|
+
if File.directory?(input)
|
|
665
|
+
raise "Error: '#{input.path}' is a directory (did you mean to use --recursive?)"
|
|
666
|
+
end
|
|
584
667
|
output = @options[:output]
|
|
585
668
|
output = input if @options[:in_place]
|
|
586
669
|
process_file(input, output)
|
|
@@ -589,20 +672,22 @@ END
|
|
|
589
672
|
private
|
|
590
673
|
|
|
591
674
|
def process_directory
|
|
592
|
-
unless input = @options[:input] = @args.shift
|
|
675
|
+
unless (input = @options[:input] = @args.shift)
|
|
593
676
|
raise "Error: directory required when using --recursive."
|
|
594
677
|
end
|
|
595
678
|
|
|
596
679
|
output = @options[:output] = @args.shift
|
|
597
680
|
raise "Error: --from required when using --recursive." unless @options[:from]
|
|
598
681
|
raise "Error: --to required when using --recursive." unless @options[:to]
|
|
599
|
-
|
|
600
|
-
|
|
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])
|
|
601
687
|
raise "Error: '#{@options[:output]}' is not a directory"
|
|
602
688
|
end
|
|
603
689
|
@options[:output] ||= @options[:input]
|
|
604
690
|
|
|
605
|
-
from = @options[:from]
|
|
606
691
|
if @options[:to] == @options[:from] && !@options[:in_place]
|
|
607
692
|
fmt = @options[:from]
|
|
608
693
|
raise "Error: converting from #{fmt} to #{fmt} without --in-place"
|
|
@@ -633,7 +718,6 @@ END
|
|
|
633
718
|
end
|
|
634
719
|
|
|
635
720
|
input = open_file(f)
|
|
636
|
-
output = @options[:in_place] ? input : open_file(output, "w")
|
|
637
721
|
process_file(input, output)
|
|
638
722
|
end
|
|
639
723
|
end
|
|
@@ -677,8 +761,8 @@ END
|
|
|
677
761
|
end
|
|
678
762
|
end
|
|
679
763
|
|
|
680
|
-
output =
|
|
681
|
-
|
|
764
|
+
output = input.path if @options[:in_place]
|
|
765
|
+
write_output(out, output)
|
|
682
766
|
rescue ::Sass::SyntaxError => e
|
|
683
767
|
raise e if @options[:trace]
|
|
684
768
|
file = " of #{e.sass_filename}" if e.sass_filename
|