sass 3.3.0 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +58 -50
- data/Rakefile +1 -4
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/VERSION_NAME +1 -1
- data/bin/sass +1 -1
- data/bin/scss +1 -1
- data/lib/sass/cache_stores/filesystem.rb +6 -2
- data/lib/sass/css.rb +1 -3
- data/lib/sass/engine.rb +37 -46
- data/lib/sass/environment.rb +13 -17
- data/lib/sass/error.rb +6 -9
- data/lib/sass/exec/base.rb +187 -0
- data/lib/sass/exec/sass_convert.rb +264 -0
- data/lib/sass/exec/sass_scss.rb +424 -0
- data/lib/sass/exec.rb +5 -771
- data/lib/sass/features.rb +7 -0
- data/lib/sass/importers/base.rb +7 -2
- data/lib/sass/importers/filesystem.rb +9 -25
- data/lib/sass/importers.rb +0 -1
- data/lib/sass/media.rb +1 -4
- data/lib/sass/plugin/compiler.rb +200 -83
- data/lib/sass/plugin/staleness_checker.rb +1 -1
- data/lib/sass/plugin.rb +3 -3
- data/lib/sass/script/css_lexer.rb +1 -1
- data/lib/sass/script/functions.rb +622 -268
- data/lib/sass/script/lexer.rb +99 -34
- data/lib/sass/script/parser.rb +24 -23
- data/lib/sass/script/tree/funcall.rb +1 -1
- data/lib/sass/script/tree/interpolation.rb +20 -2
- data/lib/sass/script/tree/selector.rb +26 -0
- data/lib/sass/script/tree/string_interpolation.rb +1 -1
- data/lib/sass/script/tree.rb +1 -0
- data/lib/sass/script/value/base.rb +7 -5
- data/lib/sass/script/value/bool.rb +0 -5
- data/lib/sass/script/value/color.rb +39 -21
- data/lib/sass/script/value/helpers.rb +107 -0
- data/lib/sass/script/value/list.rb +0 -15
- data/lib/sass/script/value/null.rb +0 -5
- data/lib/sass/script/value/number.rb +62 -14
- data/lib/sass/script/value/string.rb +59 -11
- data/lib/sass/script/value.rb +0 -1
- data/lib/sass/scss/css_parser.rb +8 -2
- data/lib/sass/scss/parser.rb +190 -328
- data/lib/sass/scss/rx.rb +15 -6
- data/lib/sass/scss/static_parser.rb +298 -1
- data/lib/sass/selector/abstract_sequence.rb +28 -13
- data/lib/sass/selector/comma_sequence.rb +92 -13
- data/lib/sass/selector/pseudo.rb +256 -0
- data/lib/sass/selector/sequence.rb +94 -24
- data/lib/sass/selector/simple.rb +14 -25
- data/lib/sass/selector/simple_sequence.rb +97 -33
- data/lib/sass/selector.rb +57 -194
- data/lib/sass/shared.rb +1 -1
- data/lib/sass/source/map.rb +26 -12
- data/lib/sass/stack.rb +0 -6
- data/lib/sass/supports.rb +2 -3
- data/lib/sass/tree/at_root_node.rb +1 -0
- data/lib/sass/tree/charset_node.rb +1 -1
- data/lib/sass/tree/directive_node.rb +8 -2
- data/lib/sass/tree/error_node.rb +18 -0
- data/lib/sass/tree/extend_node.rb +1 -1
- data/lib/sass/tree/function_node.rb +4 -0
- data/lib/sass/tree/keyframe_rule_node.rb +15 -0
- data/lib/sass/tree/prop_node.rb +1 -1
- data/lib/sass/tree/rule_node.rb +12 -7
- data/lib/sass/tree/visitors/check_nesting.rb +38 -10
- data/lib/sass/tree/visitors/convert.rb +16 -18
- data/lib/sass/tree/visitors/cssize.rb +29 -29
- data/lib/sass/tree/visitors/deep_copy.rb +5 -0
- data/lib/sass/tree/visitors/perform.rb +45 -33
- data/lib/sass/tree/visitors/set_options.rb +14 -0
- data/lib/sass/tree/visitors/to_css.rb +15 -14
- data/lib/sass/util/subset_map.rb +1 -1
- data/lib/sass/util.rb +222 -99
- data/lib/sass/version.rb +5 -5
- data/lib/sass.rb +0 -5
- data/test/sass/cache_test.rb +62 -20
- data/test/sass/callbacks_test.rb +1 -1
- data/test/sass/compiler_test.rb +19 -10
- data/test/sass/conversion_test.rb +58 -1
- data/test/sass/css2sass_test.rb +23 -4
- data/test/sass/encoding_test.rb +219 -0
- data/test/sass/engine_test.rb +136 -199
- data/test/sass/exec_test.rb +2 -2
- data/test/sass/extend_test.rb +236 -19
- data/test/sass/functions_test.rb +295 -253
- data/test/sass/importer_test.rb +31 -21
- data/test/sass/logger_test.rb +1 -1
- data/test/sass/more_results/more_import.css +1 -1
- data/test/sass/plugin_test.rb +14 -13
- data/test/sass/results/compact.css +1 -1
- data/test/sass/results/complex.css +4 -4
- data/test/sass/results/expanded.css +1 -1
- data/test/sass/results/import.css +1 -1
- data/test/sass/results/import_charset_ibm866.css +2 -2
- data/test/sass/results/mixins.css +17 -17
- data/test/sass/results/nested.css +1 -1
- data/test/sass/results/parent_ref.css +2 -2
- data/test/sass/results/script.css +3 -3
- data/test/sass/results/scss_import.css +1 -1
- data/test/sass/script_conversion_test.rb +10 -7
- data/test/sass/script_test.rb +288 -74
- data/test/sass/scss/css_test.rb +141 -24
- data/test/sass/scss/rx_test.rb +4 -4
- data/test/sass/scss/scss_test.rb +457 -18
- data/test/sass/source_map_test.rb +115 -25
- data/test/sass/superselector_test.rb +191 -0
- data/test/sass/templates/scss_import.scss +2 -1
- data/test/sass/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
- data/test/sass/util/normalized_map_test.rb +1 -1
- data/test/sass/util/subset_map_test.rb +2 -2
- data/test/sass/util_test.rb +31 -1
- data/test/sass/value_helpers_test.rb +5 -7
- data/test/test_helper.rb +2 -2
- data/vendor/listen/CHANGELOG.md +1 -228
- data/vendor/listen/Gemfile +5 -15
- data/vendor/listen/README.md +111 -77
- data/vendor/listen/Rakefile +0 -42
- data/vendor/listen/lib/listen/adapter.rb +195 -82
- data/vendor/listen/lib/listen/adapters/bsd.rb +27 -64
- data/vendor/listen/lib/listen/adapters/darwin.rb +21 -58
- data/vendor/listen/lib/listen/adapters/linux.rb +23 -55
- data/vendor/listen/lib/listen/adapters/polling.rb +25 -34
- data/vendor/listen/lib/listen/adapters/windows.rb +50 -46
- data/vendor/listen/lib/listen/directory_record.rb +96 -61
- data/vendor/listen/lib/listen/listener.rb +135 -37
- data/vendor/listen/lib/listen/turnstile.rb +9 -5
- data/vendor/listen/lib/listen/version.rb +1 -1
- data/vendor/listen/lib/listen.rb +33 -19
- data/vendor/listen/listen.gemspec +6 -0
- data/vendor/listen/spec/listen/adapter_spec.rb +43 -77
- data/vendor/listen/spec/listen/adapters/polling_spec.rb +8 -8
- data/vendor/listen/spec/listen/directory_record_spec.rb +81 -56
- data/vendor/listen/spec/listen/listener_spec.rb +128 -39
- data/vendor/listen/spec/listen_spec.rb +15 -21
- data/vendor/listen/spec/spec_helper.rb +4 -0
- data/vendor/listen/spec/support/adapter_helper.rb +52 -15
- data/vendor/listen/spec/support/directory_record_helper.rb +7 -5
- data/vendor/listen/spec/support/listeners_helper.rb +30 -7
- metadata +25 -22
- data/ext/mkrf_conf.rb +0 -27
- data/lib/sass/importers/deprecated_path.rb +0 -51
- data/lib/sass/script/value/deprecated_false.rb +0 -55
- data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
- data/vendor/listen/lib/listen/multi_listener.rb +0 -143
- data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
- data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
data/lib/sass/source/map.rb
CHANGED
@@ -68,12 +68,6 @@ module Sass::Source
|
|
68
68
|
# it will be inferred from `:css_path` and `:sourcemap_path` using the
|
69
69
|
# assumption that the local file system has the same layout as the server.
|
70
70
|
#
|
71
|
-
# If any source stylesheets use the default filesystem importer, sourcemap
|
72
|
-
# generation will fail unless the `:sourcemap_path` option is specified.
|
73
|
-
# The layout of the local file system is assumed to be the same as the
|
74
|
-
# layout of the server for the purposes of linking to source stylesheets
|
75
|
-
# that use the filesystem importer.
|
76
|
-
#
|
77
71
|
# Regardless of which options are passed to this method, source stylesheets
|
78
72
|
# that are imported using a non-default importer will only be linked to in
|
79
73
|
# the source map if their importers implement
|
@@ -85,6 +79,8 @@ module Sass::Source
|
|
85
79
|
# The local path of the CSS output file.
|
86
80
|
# @option options :sourcemap_path [String]
|
87
81
|
# The (eventual) local path of the sourcemap file.
|
82
|
+
# @option options :type [Symbol]
|
83
|
+
# `:auto` (default), `:file`, or `:inline`.
|
88
84
|
# @return [String] The JSON string.
|
89
85
|
# @raise [ArgumentError] If neither `:css_uri` nor `:css_path` and
|
90
86
|
# `:sourcemap_path` are specified.
|
@@ -97,15 +93,16 @@ module Sass::Source
|
|
97
93
|
raise ArgumentError.new("Sass::Source::Map#to_json requires either " \
|
98
94
|
"the :css_uri option or both the :css_path and :soucemap_path options.")
|
99
95
|
end
|
100
|
-
css_path &&=
|
101
|
-
sourcemap_path &&=
|
102
|
-
css_uri ||= css_path.relative_path_from(sourcemap_path.dirname)
|
96
|
+
css_path &&= Sass::Util.pathname(Sass::Util.absolute_path(css_path))
|
97
|
+
sourcemap_path &&= Sass::Util.pathname(Sass::Util.absolute_path(sourcemap_path))
|
98
|
+
css_uri ||= Sass::Util.file_uri_from_path(css_path.relative_path_from(sourcemap_path.dirname))
|
103
99
|
|
104
100
|
result = "{\n"
|
105
101
|
write_json_field(result, "version", 3, true)
|
106
102
|
|
107
103
|
source_uri_to_id = {}
|
108
104
|
id_to_source_uri = {}
|
105
|
+
id_to_contents = {} if options[:type] == :inline
|
109
106
|
next_source_id = 0
|
110
107
|
line_data = []
|
111
108
|
segment_data_for_line = []
|
@@ -119,9 +116,15 @@ module Sass::Source
|
|
119
116
|
|
120
117
|
@data.each do |m|
|
121
118
|
file, importer = m.input.file, m.input.importer
|
122
|
-
|
123
|
-
|
124
|
-
|
119
|
+
|
120
|
+
if options[:type] == :inline
|
121
|
+
source_uri = file
|
122
|
+
else
|
123
|
+
sourcemap_dir = sourcemap_path && sourcemap_path.dirname.to_s
|
124
|
+
sourcemap_dir = nil if options[:type] == :file
|
125
|
+
source_uri = importer && importer.public_url(file, sourcemap_dir)
|
126
|
+
next unless source_uri
|
127
|
+
end
|
125
128
|
|
126
129
|
current_source_id = source_uri_to_id[source_uri]
|
127
130
|
unless current_source_id
|
@@ -130,6 +133,11 @@ module Sass::Source
|
|
130
133
|
|
131
134
|
source_uri_to_id[source_uri] = current_source_id
|
132
135
|
id_to_source_uri[current_source_id] = source_uri
|
136
|
+
|
137
|
+
if options[:type] == :inline
|
138
|
+
id_to_contents[current_source_id] =
|
139
|
+
importer.find(file, {}).instance_variable_get('@template')
|
140
|
+
end
|
133
141
|
end
|
134
142
|
|
135
143
|
[
|
@@ -174,6 +182,12 @@ module Sass::Source
|
|
174
182
|
source_names = []
|
175
183
|
(0...next_source_id).each {|id| source_names.push(id_to_source_uri[id].to_s)}
|
176
184
|
write_json_field(result, "sources", source_names)
|
185
|
+
|
186
|
+
if options[:type] == :inline
|
187
|
+
write_json_field(result, "sourcesContent",
|
188
|
+
(0...next_source_id).map {|id| id_to_contents[id]})
|
189
|
+
end
|
190
|
+
|
177
191
|
write_json_field(result, "names", [])
|
178
192
|
write_json_field(result, "file", css_uri)
|
179
193
|
|
data/lib/sass/stack.rb
CHANGED
data/lib/sass/supports.rb
CHANGED
@@ -203,8 +203,7 @@ module Sass::Supports
|
|
203
203
|
end
|
204
204
|
|
205
205
|
def perform(env)
|
206
|
-
|
207
|
-
@resolved_value = val.is_a?(Sass::Script::Value::String) ? val.value : val.to_s
|
206
|
+
@resolved_value = value.perform(env).to_s(:quote => :none)
|
208
207
|
end
|
209
208
|
|
210
209
|
def to_css
|
@@ -212,7 +211,7 @@ module Sass::Supports
|
|
212
211
|
end
|
213
212
|
|
214
213
|
def to_src(options)
|
215
|
-
|
214
|
+
@value.to_sass(options)
|
216
215
|
end
|
217
216
|
|
218
217
|
def deep_copy
|
@@ -70,6 +70,7 @@ module Sass
|
|
70
70
|
# @return [Boolean]
|
71
71
|
def exclude_node?(node)
|
72
72
|
return exclude?(node.name.gsub(/^@/, '')) if node.is_a?(Sass::Tree::DirectiveNode)
|
73
|
+
return exclude?('keyframes') if node.is_a?(Sass::Tree::KeyframeRuleNode)
|
73
74
|
exclude?('rule') && node.is_a?(Sass::Tree::RuleNode)
|
74
75
|
end
|
75
76
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Sass::Tree
|
2
|
-
# A static node representing an
|
2
|
+
# A static node representing an unprocessed Sass `@`-directive.
|
3
3
|
# Directives known to Sass, like `@for` and `@debug`,
|
4
4
|
# are handled by their own nodes;
|
5
5
|
# only CSS directives like `@media` and `@font-face` become {DirectiveNode}s.
|
@@ -43,7 +43,13 @@ module Sass::Tree
|
|
43
43
|
|
44
44
|
# @return [String] The name of the directive, including `@`.
|
45
45
|
def name
|
46
|
-
value.first.gsub(/ .*$/, '')
|
46
|
+
@name ||= value.first.gsub(/ .*$/, '')
|
47
|
+
end
|
48
|
+
|
49
|
+
# Strips out any vendor prefixes and downcases the directive name.
|
50
|
+
# @return [String] The normalized name of the directive.
|
51
|
+
def normalized_name
|
52
|
+
@normalized_name ||= name.gsub(/^(@)(?:-[a-zA-Z0-9]+-)?/, '\1').downcase
|
47
53
|
end
|
48
54
|
|
49
55
|
def bubbles?
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Sass
|
2
|
+
module Tree
|
3
|
+
# A dynamic node representing a Sass `@error` statement.
|
4
|
+
#
|
5
|
+
# @see Sass::Tree
|
6
|
+
class ErrorNode < Node
|
7
|
+
# The expression to print.
|
8
|
+
# @return [Script::Tree::Node]
|
9
|
+
attr_accessor :expr
|
10
|
+
|
11
|
+
# @param expr [Script::Tree::Node] The expression to print
|
12
|
+
def initialize(expr)
|
13
|
+
@expr = expr
|
14
|
+
super()
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Sass::Tree
|
2
|
+
class KeyframeRuleNode < Node
|
3
|
+
# The text of the directive after any interpolated SassScript has been resolved.
|
4
|
+
# Since this is only a static node, this is the only value property.
|
5
|
+
#
|
6
|
+
# @return [String]
|
7
|
+
attr_accessor :resolved_value
|
8
|
+
|
9
|
+
# @param resolved_value [String] See \{#resolved_value}
|
10
|
+
def initialize(resolved_value)
|
11
|
+
@resolved_value = resolved_value
|
12
|
+
super()
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/sass/tree/prop_node.rb
CHANGED
@@ -97,7 +97,7 @@ module Sass::Tree
|
|
97
97
|
# @param opts [{Symbol => Object}] The options hash for the tree.
|
98
98
|
# @param fmt [Symbol] `:scss` or `:sass`.
|
99
99
|
def declaration(opts = {:old => @prop_syntax == :old}, fmt = :sass)
|
100
|
-
name = self.name.map {|n| n.is_a?(String) ? n :
|
100
|
+
name = self.name.map {|n| n.is_a?(String) ? n : n.to_sass(opts)}.join
|
101
101
|
if name[0] == ?:
|
102
102
|
raise Sass::SyntaxError.new("The \"#{name}: #{self.class.val_to_sass(value, opts)}\"" +
|
103
103
|
" hack is not allowed in the Sass indented syntax")
|
data/lib/sass/tree/rule_node.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
|
3
3
|
module Sass::Tree
|
4
|
-
# A static node
|
4
|
+
# A static node representing a CSS rule.
|
5
5
|
#
|
6
6
|
# @see Sass::Tree
|
7
7
|
class RuleNode < Node
|
@@ -60,15 +60,20 @@ module Sass::Tree
|
|
60
60
|
# @return [String]
|
61
61
|
attr_accessor :stack_trace
|
62
62
|
|
63
|
-
# @param rule [Array<String, Sass::Script::Tree::Node
|
63
|
+
# @param rule [Array<String, Sass::Script::Tree::Node>, Sass::Selector::CommaSequence]
|
64
|
+
# The CSS rule, either unparsed or parsed.
|
64
65
|
# @param selector_source_range [Sass::Source::Range]
|
65
|
-
# The CSS rule. See \{#rule}
|
66
66
|
def initialize(rule, selector_source_range = nil)
|
67
|
-
|
68
|
-
|
67
|
+
if rule.is_a?(Sass::Selector::CommaSequence)
|
68
|
+
@rule = [rule.to_s]
|
69
|
+
@parsed_rules = rule
|
70
|
+
else
|
71
|
+
merged = Sass::Util.merge_adjacent_strings(rule)
|
72
|
+
@rule = Sass::Util.strip_string_array(merged)
|
73
|
+
try_to_parse_non_interpolated_rules
|
74
|
+
end
|
69
75
|
@selector_source_range = selector_source_range
|
70
76
|
@tabs = 0
|
71
|
-
try_to_parse_non_interpolated_rules
|
72
77
|
super()
|
73
78
|
end
|
74
79
|
|
@@ -130,7 +135,7 @@ module Sass::Tree
|
|
130
135
|
if @rule.all? {|t| t.kind_of?(String)}
|
131
136
|
# We don't use real filename/line info because we don't have it yet.
|
132
137
|
# When we get it, we'll set it on the parsed rules if possible.
|
133
|
-
parser = Sass::SCSS::StaticParser.new(@rule.join.strip,
|
138
|
+
parser = Sass::SCSS::StaticParser.new(@rule.join.strip, nil, nil, 1)
|
134
139
|
# rubocop:disable RescueModifier
|
135
140
|
@parsed_rules = parser.parse_selector rescue nil
|
136
141
|
# rubocop:enable RescueModifier
|
@@ -23,13 +23,34 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
|
|
23
23
|
SCRIPT_NODES = [Sass::Tree::ImportNode] + CONTROL_NODES
|
24
24
|
def visit_children(parent)
|
25
25
|
old_parent = @parent
|
26
|
-
|
27
|
-
|
26
|
+
|
27
|
+
# When checking a static tree, resolve at-roots to be sure they won't send
|
28
|
+
# nodes where they don't belong.
|
29
|
+
if parent.is_a?(Sass::Tree::AtRootNode) && parent.resolved_value
|
30
|
+
old_parents = @parents
|
31
|
+
@parents = @parents.reject {|p| parent.exclude_node?(p)}
|
32
|
+
@parent = Sass::Util.enum_with_index(@parents.reverse).
|
33
|
+
find {|p, i| !transparent_parent?(p, @parents[-i - 2])}.first
|
34
|
+
|
35
|
+
begin
|
36
|
+
return super
|
37
|
+
ensure
|
38
|
+
@parents = old_parents
|
39
|
+
@parent = old_parent
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
unless transparent_parent?(parent, old_parent)
|
44
|
+
@parent = parent
|
45
|
+
end
|
46
|
+
|
28
47
|
@parents.push parent
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
48
|
+
begin
|
49
|
+
super
|
50
|
+
ensure
|
51
|
+
@parent = old_parent
|
52
|
+
@parents.pop
|
53
|
+
end
|
33
54
|
end
|
34
55
|
|
35
56
|
def visit_root(node)
|
@@ -102,7 +123,7 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
|
|
102
123
|
|
103
124
|
VALID_FUNCTION_CHILDREN = [
|
104
125
|
Sass::Tree::CommentNode, Sass::Tree::DebugNode, Sass::Tree::ReturnNode,
|
105
|
-
Sass::Tree::VariableNode, Sass::Tree::WarnNode
|
126
|
+
Sass::Tree::VariableNode, Sass::Tree::WarnNode, Sass::Tree::ErrorNode
|
106
127
|
] + CONTROL_NODES
|
107
128
|
def invalid_function_child?(parent, child)
|
108
129
|
unless is_any_of?(child, VALID_FUNCTION_CHILDREN)
|
@@ -119,9 +140,8 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
|
|
119
140
|
end
|
120
141
|
end
|
121
142
|
|
122
|
-
VALID_PROP_PARENTS = [Sass::Tree::RuleNode, Sass::Tree::PropNode,
|
123
|
-
Sass::Tree::MixinDefNode, Sass::Tree::DirectiveNode,
|
124
|
-
Sass::Tree::MixinNode]
|
143
|
+
VALID_PROP_PARENTS = [Sass::Tree::RuleNode, Sass::Tree::KeyframeRuleNode, Sass::Tree::PropNode,
|
144
|
+
Sass::Tree::MixinDefNode, Sass::Tree::DirectiveNode, Sass::Tree::MixinNode]
|
125
145
|
def invalid_prop_parent?(parent, child)
|
126
146
|
unless is_any_of?(parent, VALID_PROP_PARENTS)
|
127
147
|
"Properties are only allowed within rules, directives, mixin includes, or other properties." +
|
@@ -135,6 +155,14 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
|
|
135
155
|
|
136
156
|
private
|
137
157
|
|
158
|
+
# Whether `parent` should be assigned to `@parent`.
|
159
|
+
def transparent_parent?(parent, grandparent)
|
160
|
+
is_any_of?(parent, SCRIPT_NODES) ||
|
161
|
+
(parent.bubbles? &&
|
162
|
+
!grandparent.is_a?(Sass::Tree::RootNode) &&
|
163
|
+
!grandparent.is_a?(Sass::Tree::AtRootNode))
|
164
|
+
end
|
165
|
+
|
138
166
|
def is_any_of?(val, classes)
|
139
167
|
classes.each do |c|
|
140
168
|
return true if val.is_a?(c)
|
@@ -96,6 +96,10 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
96
96
|
"#{tab_str}@debug #{node.expr.to_sass(@options)}#{semi}\n"
|
97
97
|
end
|
98
98
|
|
99
|
+
def visit_error(node)
|
100
|
+
"#{tab_str}@error #{node.expr.to_sass(@options)}#{semi}\n"
|
101
|
+
end
|
102
|
+
|
99
103
|
def visit_directive(node)
|
100
104
|
res = "#{tab_str}#{interp_to_src(node.value)}"
|
101
105
|
res.gsub!(/^@import \#\{(.*)\}([^}]*)$/, '@import \1\2')
|
@@ -236,12 +240,13 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
236
240
|
end
|
237
241
|
|
238
242
|
def visit_rule(node)
|
243
|
+
rule = node.parsed_rules ? [node.parsed_rules.to_s] : node.rule
|
239
244
|
if @format == :sass
|
240
|
-
name = selector_to_sass(
|
245
|
+
name = selector_to_sass(rule)
|
241
246
|
name = "\\" + name if name[0] == ?:
|
242
247
|
name.gsub(/^/, tab_str) + yield
|
243
248
|
elsif @format == :scss
|
244
|
-
name = selector_to_scss(
|
249
|
+
name = selector_to_scss(rule)
|
245
250
|
res = name + yield
|
246
251
|
if node.children.last.is_a?(Sass::Tree::CommentNode) && node.children.last.type == :silent
|
247
252
|
res.slice!(-3..-1)
|
@@ -278,26 +283,19 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
278
283
|
private
|
279
284
|
|
280
285
|
def interp_to_src(interp)
|
281
|
-
interp.map
|
282
|
-
next r if r.is_a?(String)
|
283
|
-
"\#{#{r.to_sass(@options)}}"
|
284
|
-
end.join
|
286
|
+
interp.map {|r| r.is_a?(String) ? r : r.to_sass(@options)}.join
|
285
287
|
end
|
286
288
|
|
287
289
|
# Like interp_to_src, but removes the unnecessary `#{}` around the keys and
|
288
290
|
# values in query expressions.
|
289
291
|
def query_interp_to_src(interp)
|
290
|
-
|
291
|
-
next
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
else
|
298
|
-
"\#{#{r.to_sass(@options)}}"
|
299
|
-
end
|
300
|
-
end.join
|
292
|
+
interp = interp.map do |e|
|
293
|
+
next e unless e.is_a?(Sass::Script::Tree::Literal)
|
294
|
+
next e unless e.value.is_a?(Sass::Script::Value::String)
|
295
|
+
e.value.value
|
296
|
+
end
|
297
|
+
|
298
|
+
interp_to_src(interp)
|
301
299
|
end
|
302
300
|
|
303
301
|
def selector_to_src(sel)
|
@@ -309,7 +307,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
309
307
|
if r.is_a?(String)
|
310
308
|
r.gsub(/(,)?([ \t]*)\n\s*/) {$1 ? "#{$1}#{$2}\n" : " "}
|
311
309
|
else
|
312
|
-
|
310
|
+
r.to_sass(@options)
|
313
311
|
end
|
314
312
|
end.join
|
315
313
|
end
|
@@ -123,29 +123,8 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
|
|
123
123
|
|
124
124
|
# Registers an extension in the `@extends` subset map.
|
125
125
|
def visit_extend(node)
|
126
|
-
node.resolved_selector
|
127
|
-
|
128
|
-
raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: can't extend nested selectors")
|
129
|
-
end
|
130
|
-
|
131
|
-
sseq = seq.members.first
|
132
|
-
if !sseq.is_a?(Sass::Selector::SimpleSequence)
|
133
|
-
raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: invalid selector")
|
134
|
-
elsif sseq.members.any? {|ss| ss.is_a?(Sass::Selector::Parent)}
|
135
|
-
raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: can't extend parent selectors")
|
136
|
-
end
|
137
|
-
|
138
|
-
sel = sseq.members
|
139
|
-
parent.resolved_rules.members.each do |member|
|
140
|
-
unless member.members.last.is_a?(Sass::Selector::SimpleSequence)
|
141
|
-
raise Sass::SyntaxError.new("#{member} can't extend: invalid selector")
|
142
|
-
end
|
143
|
-
|
144
|
-
parent_directives = @parents.select {|p| p.is_a?(Sass::Tree::DirectiveNode)}
|
145
|
-
@extends[sel] = Extend.new(member, sel, node, parent_directives, :not_found)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
126
|
+
parent.resolved_rules.populate_extends(@extends, node.resolved_selector, node,
|
127
|
+
@parents.select {|p| p.is_a?(Sass::Tree::DirectiveNode)})
|
149
128
|
[]
|
150
129
|
end
|
151
130
|
|
@@ -232,6 +211,14 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
|
|
232
211
|
rules
|
233
212
|
end
|
234
213
|
|
214
|
+
def visit_keyframerule(node)
|
215
|
+
return node unless node.has_children
|
216
|
+
|
217
|
+
yield
|
218
|
+
|
219
|
+
debubble(node.children, node)
|
220
|
+
end
|
221
|
+
|
235
222
|
# Bubbles a directive up through RuleNodes.
|
236
223
|
def visit_directive(node)
|
237
224
|
return node unless node.has_children
|
@@ -249,7 +236,8 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
|
|
249
236
|
child.node.resolved_value == node.resolved_value
|
250
237
|
end
|
251
238
|
|
252
|
-
|
239
|
+
# We know empty @keyframes directives do nothing.
|
240
|
+
if directive_exists || node.name == '@keyframes'
|
253
241
|
[]
|
254
242
|
else
|
255
243
|
empty_node = node.dup
|
@@ -315,19 +303,31 @@ class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
|
|
315
303
|
# omitted.
|
316
304
|
# @return [List<Sass::Tree::Node, Bubble>]
|
317
305
|
def debubble(children, parent = nil)
|
306
|
+
# Keep track of the previous parent so that we don't divide `parent`
|
307
|
+
# unnecessarily if the `@at-root` doesn't produce any new nodes (e.g.
|
308
|
+
# `@at-root {@extend %foo}`).
|
309
|
+
previous_parent = nil
|
310
|
+
|
318
311
|
Sass::Util.slice_by(children) {|c| c.is_a?(Bubble)}.map do |(is_bubble, slice)|
|
319
312
|
unless is_bubble
|
320
313
|
next slice unless parent
|
321
|
-
|
322
|
-
|
323
|
-
|
314
|
+
if previous_parent
|
315
|
+
previous_parent.children.push(*slice)
|
316
|
+
next []
|
317
|
+
else
|
318
|
+
previous_parent = new_parent = parent.dup
|
319
|
+
new_parent.children = slice
|
320
|
+
next new_parent
|
321
|
+
end
|
324
322
|
end
|
325
323
|
|
326
|
-
|
324
|
+
slice.map do |bubble|
|
327
325
|
next unless (node = block_given? ? yield(bubble.node) : bubble.node)
|
328
326
|
node.tabs += bubble.tabs
|
329
327
|
node.group_end = bubble.group_end
|
330
|
-
[visit(node)].flatten
|
328
|
+
results = [visit(node)].flatten
|
329
|
+
previous_parent = nil unless results.empty?
|
330
|
+
results
|
331
331
|
end.compact
|
332
332
|
end.flatten
|
333
333
|
end
|
@@ -207,6 +207,17 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
207
207
|
[]
|
208
208
|
end
|
209
209
|
|
210
|
+
# Throws the expression as an error.
|
211
|
+
def visit_error(node)
|
212
|
+
res = node.expr.perform(@environment)
|
213
|
+
if res.is_a?(Sass::Script::Value::String)
|
214
|
+
res = res.value
|
215
|
+
else
|
216
|
+
res = res.to_sass
|
217
|
+
end
|
218
|
+
raise Sass::SyntaxError.new(res)
|
219
|
+
end
|
220
|
+
|
210
221
|
# Runs the child nodes once for each value in the list.
|
211
222
|
def visit_each(node)
|
212
223
|
list = node.list.perform(@environment)
|
@@ -377,18 +388,31 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
377
388
|
# Runs SassScript interpolation in the selector,
|
378
389
|
# and then parses the result into a {Sass::Selector::CommaSequence}.
|
379
390
|
def visit_rule(node)
|
380
|
-
old_at_root_without_rule
|
391
|
+
old_at_root_without_rule = @at_root_without_rule
|
381
392
|
parser = Sass::SCSS::StaticParser.new(run_interp(node.rule),
|
382
393
|
node.filename, node.options[:importer], node.line)
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
394
|
+
if @in_keyframes
|
395
|
+
keyframe_rule_node = Sass::Tree::KeyframeRuleNode.new(parser.parse_keyframes_selector)
|
396
|
+
keyframe_rule_node.options = node.options
|
397
|
+
keyframe_rule_node.line = node.line
|
398
|
+
keyframe_rule_node.filename = node.filename
|
399
|
+
keyframe_rule_node.source_range = node.source_range
|
400
|
+
with_environment Sass::Environment.new(@environment, node.options) do
|
401
|
+
keyframe_rule_node.children = node.children.map {|c| visit(c)}.flatten
|
402
|
+
end
|
403
|
+
keyframe_rule_node
|
404
|
+
else
|
405
|
+
@at_root_without_rule = false
|
406
|
+
node.parsed_rules ||= parser.parse_selector
|
407
|
+
node.resolved_rules = node.parsed_rules.resolve_parent_refs(
|
408
|
+
@environment.selector, !old_at_root_without_rule)
|
409
|
+
node.stack_trace = @environment.stack.to_s if node.options[:trace_selectors]
|
410
|
+
with_environment Sass::Environment.new(@environment, node.options) do
|
411
|
+
@environment.selector = node.resolved_rules
|
412
|
+
node.children = node.children.map {|c| visit(c)}.flatten
|
413
|
+
end
|
414
|
+
node
|
390
415
|
end
|
391
|
-
node
|
392
416
|
ensure
|
393
417
|
@at_root_without_rule = old_at_root_without_rule
|
394
418
|
end
|
@@ -405,36 +429,24 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
|
405
429
|
end
|
406
430
|
|
407
431
|
old_at_root_without_rule = @at_root_without_rule
|
432
|
+
old_in_keyframes = @in_keyframes
|
408
433
|
@at_root_without_rule = true if node.exclude?('rule')
|
434
|
+
@in_keyframes = false if node.exclude?('keyframes')
|
409
435
|
yield
|
410
436
|
ensure
|
437
|
+
@in_keyframes = old_in_keyframes
|
411
438
|
@at_root_without_rule = old_at_root_without_rule
|
412
439
|
end
|
413
440
|
|
414
441
|
# Loads the new variable value into the environment.
|
415
442
|
def visit_variable(node)
|
416
443
|
env = @environment
|
417
|
-
|
418
|
-
if node.
|
419
|
-
|
420
|
-
|
421
|
-
!env.global_env.global_warning_given.include?(identifier)
|
422
|
-
env.global_env.global_warning_given.add(identifier)
|
423
|
-
var_expr = "$#{node.name}: #{node.expr.to_sass(env.options)} !global"
|
424
|
-
var_expr << " !default" if node.guarded
|
425
|
-
location = "on line #{node.line}"
|
426
|
-
location << " of #{node.filename}" if node.filename
|
427
|
-
Sass::Util.sass_warn <<WARNING
|
428
|
-
DEPRECATION WARNING #{location}:
|
429
|
-
Assigning to global variable "$#{node.name}" by default is deprecated.
|
430
|
-
In future versions of Sass, this will create a new local variable.
|
431
|
-
If you want to assign to the global variable, use "#{var_expr}" instead.
|
432
|
-
Note that this will be incompatible with Sass 3.2.
|
433
|
-
WARNING
|
444
|
+
env = env.global_env if node.global
|
445
|
+
if node.guarded
|
446
|
+
var = env.var(node.name)
|
447
|
+
return [] if var && !var.null?
|
434
448
|
end
|
435
449
|
|
436
|
-
var = env.var(node.name)
|
437
|
-
return [] if node.guarded && var && !var.null?
|
438
450
|
val = node.expr.perform(@environment)
|
439
451
|
if node.expr.source_range
|
440
452
|
val.source_range = node.expr.source_range
|
@@ -466,10 +478,13 @@ WARNING
|
|
466
478
|
|
467
479
|
def visit_directive(node)
|
468
480
|
node.resolved_value = run_interp(node.value)
|
481
|
+
old_in_keyframes, @in_keyframes = @in_keyframes, node.normalized_name == "@keyframes"
|
469
482
|
with_environment Sass::Environment.new(@environment) do
|
470
483
|
node.children = node.children.map {|c| visit(c)}.flatten
|
471
484
|
node
|
472
485
|
end
|
486
|
+
ensure
|
487
|
+
@in_keyframes = old_in_keyframes
|
473
488
|
end
|
474
489
|
|
475
490
|
def visit_media(node)
|
@@ -487,7 +502,7 @@ WARNING
|
|
487
502
|
|
488
503
|
def visit_cssimport(node)
|
489
504
|
node.resolved_uri = run_interp([node.uri])
|
490
|
-
if node.query
|
505
|
+
if node.query && !node.query.empty?
|
491
506
|
parser = Sass::SCSS::StaticParser.new(run_interp(node.query),
|
492
507
|
node.filename, node.options[:importer], node.line)
|
493
508
|
node.resolved_query ||= parser.parse_media_query_list
|
@@ -500,10 +515,7 @@ WARNING
|
|
500
515
|
def run_interp_no_strip(text)
|
501
516
|
text.map do |r|
|
502
517
|
next r if r.is_a?(String)
|
503
|
-
|
504
|
-
# Interpolated strings should never render with quotes
|
505
|
-
next val.value if val.is_a?(Sass::Script::Value::String)
|
506
|
-
val.to_s
|
518
|
+
r.perform(@environment).to_s(:quote => :none)
|
507
519
|
end.join
|
508
520
|
end
|
509
521
|
|