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