sass 3.3.0 → 3.4.25
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/.yardopts +3 -1
- data/CODE_OF_CONDUCT.md +10 -0
- data/CONTRIBUTING.md +148 -0
- data/MIT-LICENSE +1 -1
- data/README.md +76 -62
- data/Rakefile +104 -24
- 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/extra/sass-spec-ref.sh +32 -0
- data/extra/update_watch.rb +1 -1
- data/lib/sass/cache_stores/filesystem.rb +9 -5
- data/lib/sass/cache_stores/memory.rb +4 -5
- data/lib/sass/callbacks.rb +2 -2
- data/lib/sass/css.rb +12 -13
- data/lib/sass/deprecation.rb +55 -0
- data/lib/sass/engine.rb +106 -70
- data/lib/sass/environment.rb +39 -19
- data/lib/sass/error.rb +17 -20
- data/lib/sass/exec/base.rb +199 -0
- data/lib/sass/exec/sass_convert.rb +283 -0
- data/lib/sass/exec/sass_scss.rb +440 -0
- data/lib/sass/exec.rb +5 -771
- data/lib/sass/features.rb +9 -2
- data/lib/sass/importers/base.rb +8 -3
- data/lib/sass/importers/filesystem.rb +30 -38
- data/lib/sass/logger/base.rb +8 -2
- data/lib/sass/logger/delayed.rb +50 -0
- data/lib/sass/logger.rb +8 -3
- data/lib/sass/media.rb +1 -4
- data/lib/sass/plugin/compiler.rb +224 -90
- data/lib/sass/plugin/configuration.rb +38 -22
- data/lib/sass/plugin/merb.rb +2 -2
- data/lib/sass/plugin/rack.rb +3 -3
- data/lib/sass/plugin/rails.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +4 -4
- data/lib/sass/plugin.rb +6 -5
- data/lib/sass/script/css_lexer.rb +1 -1
- data/lib/sass/script/css_parser.rb +2 -3
- data/lib/sass/script/css_variable_warning.rb +52 -0
- data/lib/sass/script/functions.rb +739 -318
- data/lib/sass/script/lexer.rb +134 -54
- data/lib/sass/script/parser.rb +252 -56
- data/lib/sass/script/tree/funcall.rb +13 -6
- data/lib/sass/script/tree/interpolation.rb +127 -4
- data/lib/sass/script/tree/list_literal.rb +31 -4
- data/lib/sass/script/tree/literal.rb +4 -0
- data/lib/sass/script/tree/node.rb +21 -3
- data/lib/sass/script/tree/operation.rb +54 -1
- data/lib/sass/script/tree/selector.rb +26 -0
- data/lib/sass/script/tree/string_interpolation.rb +59 -38
- data/lib/sass/script/tree/variable.rb +1 -1
- data/lib/sass/script/tree.rb +1 -0
- data/lib/sass/script/value/base.rb +17 -14
- data/lib/sass/script/value/bool.rb +0 -5
- data/lib/sass/script/value/color.rb +78 -42
- data/lib/sass/script/value/helpers.rb +119 -2
- data/lib/sass/script/value/list.rb +0 -15
- data/lib/sass/script/value/map.rb +1 -1
- data/lib/sass/script/value/null.rb +0 -5
- data/lib/sass/script/value/number.rb +112 -31
- data/lib/sass/script/value/string.rb +102 -13
- data/lib/sass/script/value.rb +0 -1
- data/lib/sass/script.rb +3 -3
- data/lib/sass/scss/css_parser.rb +24 -4
- data/lib/sass/scss/parser.rb +290 -383
- data/lib/sass/scss/rx.rb +17 -9
- data/lib/sass/scss/static_parser.rb +306 -4
- data/lib/sass/scss.rb +0 -2
- data/lib/sass/selector/abstract_sequence.rb +35 -18
- data/lib/sass/selector/comma_sequence.rb +114 -19
- data/lib/sass/selector/pseudo.rb +266 -0
- data/lib/sass/selector/sequence.rb +146 -40
- data/lib/sass/selector/simple.rb +22 -33
- data/lib/sass/selector/simple_sequence.rb +122 -39
- data/lib/sass/selector.rb +57 -197
- data/lib/sass/shared.rb +2 -2
- data/lib/sass/source/map.rb +31 -14
- data/lib/sass/source/position.rb +4 -4
- data/lib/sass/stack.rb +2 -8
- data/lib/sass/supports.rb +10 -13
- data/lib/sass/tree/at_root_node.rb +1 -0
- data/lib/sass/tree/charset_node.rb +1 -1
- data/lib/sass/tree/comment_node.rb +1 -1
- data/lib/sass/tree/css_import_node.rb +9 -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 +9 -0
- data/lib/sass/tree/import_node.rb +6 -5
- data/lib/sass/tree/keyframe_rule_node.rb +15 -0
- data/lib/sass/tree/node.rb +5 -3
- data/lib/sass/tree/prop_node.rb +6 -7
- data/lib/sass/tree/rule_node.rb +26 -11
- data/lib/sass/tree/visitors/check_nesting.rb +56 -32
- data/lib/sass/tree/visitors/convert.rb +59 -44
- data/lib/sass/tree/visitors/cssize.rb +34 -30
- data/lib/sass/tree/visitors/deep_copy.rb +6 -1
- data/lib/sass/tree/visitors/extend.rb +15 -13
- data/lib/sass/tree/visitors/perform.rb +87 -50
- data/lib/sass/tree/visitors/set_options.rb +15 -1
- data/lib/sass/tree/visitors/to_css.rb +72 -43
- data/lib/sass/util/multibyte_string_scanner.rb +0 -2
- data/lib/sass/util/normalized_map.rb +0 -1
- data/lib/sass/util/subset_map.rb +2 -3
- data/lib/sass/util.rb +334 -154
- data/lib/sass/version.rb +7 -7
- data/lib/sass.rb +10 -8
- data/test/sass/cache_test.rb +62 -20
- data/test/sass/callbacks_test.rb +1 -1
- data/test/sass/compiler_test.rb +24 -11
- data/test/sass/conversion_test.rb +241 -50
- data/test/sass/css2sass_test.rb +73 -5
- data/test/sass/css_variable_test.rb +132 -0
- data/test/sass/encoding_test.rb +219 -0
- data/test/sass/engine_test.rb +343 -260
- data/test/sass/exec_test.rb +12 -2
- data/test/sass/extend_test.rb +333 -44
- data/test/sass/functions_test.rb +353 -260
- data/test/sass/importer_test.rb +40 -21
- data/test/sass/logger_test.rb +1 -1
- data/test/sass/more_results/more_import.css +1 -1
- data/test/sass/more_templates/more1.sass +10 -10
- data/test/sass/more_templates/more_import.sass +2 -2
- data/test/sass/plugin_test.rb +24 -21
- 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 +5 -5
- data/test/sass/results/scss_import.css +1 -1
- data/test/sass/script_conversion_test.rb +71 -39
- data/test/sass/script_test.rb +714 -123
- data/test/sass/scss/css_test.rb +213 -30
- data/test/sass/scss/rx_test.rb +8 -4
- data/test/sass/scss/scss_test.rb +766 -22
- data/test/sass/source_map_test.rb +263 -95
- data/test/sass/superselector_test.rb +210 -0
- data/test/sass/templates/_partial.sass +1 -1
- data/test/sass/templates/basic.sass +10 -10
- data/test/sass/templates/bork1.sass +1 -1
- data/test/sass/templates/bork5.sass +1 -1
- data/test/sass/templates/compact.sass +10 -10
- data/test/sass/templates/complex.sass +187 -187
- data/test/sass/templates/compressed.sass +10 -10
- data/test/sass/templates/expanded.sass +10 -10
- data/test/sass/templates/import.sass +2 -2
- data/test/sass/templates/importee.sass +3 -3
- data/test/sass/templates/mixins.sass +22 -22
- data/test/sass/templates/multiline.sass +4 -4
- data/test/sass/templates/nested.sass +13 -13
- data/test/sass/templates/parent_ref.sass +12 -12
- data/test/sass/templates/script.sass +70 -70
- data/test/sass/templates/scss_import.scss +2 -1
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +1 -1
- data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +2 -2
- data/test/sass/templates/subdir/subdir.sass +3 -3
- data/test/sass/templates/units.sass +10 -10
- data/test/sass/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +11 -3
- 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 +46 -45
- data/test/sass/value_helpers_test.rb +5 -7
- data/test/sass-spec.yml +3 -0
- data/test/test_helper.rb +7 -6
- 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 +310 -300
- data/CONTRIBUTING +0 -3
- data/ext/mkrf_conf.rb +0 -27
- data/lib/sass/script/value/deprecated_false.rb +0 -55
- data/lib/sass/scss/script_lexer.rb +0 -15
- data/lib/sass/scss/script_parser.rb +0 -25
- 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
@@ -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
|
@@ -20,6 +20,12 @@ module Sass
|
|
20
20
|
# @return [Script::Tree::Node?]
|
21
21
|
attr_accessor :splat
|
22
22
|
|
23
|
+
# Strips out any vendor prefixes.
|
24
|
+
# @return [String] The normalized name of the directive.
|
25
|
+
def normalized_name
|
26
|
+
@normalized_name ||= name.gsub(/^(?:-[a-zA-Z0-9]+-)?/, '\1')
|
27
|
+
end
|
28
|
+
|
23
29
|
# @param name [String] The function name
|
24
30
|
# @param args [Array<(Script::Tree::Node, Script::Tree::Node)>]
|
25
31
|
# The arguments for the function.
|
@@ -29,6 +35,9 @@ module Sass
|
|
29
35
|
@args = args
|
30
36
|
@splat = splat
|
31
37
|
super()
|
38
|
+
|
39
|
+
return unless %w(and or not).include?(name)
|
40
|
+
raise Sass::SyntaxError.new("Invalid function name \"#{name}\".")
|
32
41
|
end
|
33
42
|
end
|
34
43
|
end
|
@@ -55,13 +55,14 @@ module Sass
|
|
55
55
|
return f if f
|
56
56
|
end
|
57
57
|
|
58
|
-
|
58
|
+
lines = ["File to import not found or unreadable: #{@imported_filename}."]
|
59
|
+
|
59
60
|
if paths.size == 1
|
60
|
-
|
61
|
-
|
62
|
-
|
61
|
+
lines << "Load path: #{paths.first}"
|
62
|
+
elsif !paths.empty?
|
63
|
+
lines << "Load paths:\n #{paths.join("\n ")}"
|
63
64
|
end
|
64
|
-
raise SyntaxError.new(
|
65
|
+
raise SyntaxError.new(lines.join("\n"))
|
65
66
|
rescue SyntaxError => e
|
66
67
|
raise SyntaxError.new(e.message, :line => line, :filename => @filename)
|
67
68
|
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/node.rb
CHANGED
@@ -69,7 +69,7 @@ module Sass
|
|
69
69
|
|
70
70
|
# The line of the document on which this node appeared.
|
71
71
|
#
|
72
|
-
# @return [
|
72
|
+
# @return [Integer]
|
73
73
|
attr_accessor :line
|
74
74
|
|
75
75
|
# The source range in the document on which this node appeared.
|
@@ -83,13 +83,15 @@ module Sass
|
|
83
83
|
attr_writer :filename
|
84
84
|
|
85
85
|
# The options hash for the node.
|
86
|
-
# See {file:SASS_REFERENCE.md#
|
86
|
+
# See {file:SASS_REFERENCE.md#Options the Sass options documentation}.
|
87
87
|
#
|
88
88
|
# @return [{Symbol => Object}]
|
89
89
|
attr_reader :options
|
90
90
|
|
91
91
|
def initialize
|
92
92
|
@children = []
|
93
|
+
@filename = nil
|
94
|
+
@options = nil
|
93
95
|
end
|
94
96
|
|
95
97
|
# Sets the options hash for the node and all its children.
|
@@ -149,7 +151,7 @@ module Sass
|
|
149
151
|
# @return [Boolean]
|
150
152
|
def invisible?; false; end
|
151
153
|
|
152
|
-
# The output style. See {file:SASS_REFERENCE.md#
|
154
|
+
# The output style. See {file:SASS_REFERENCE.md#Options the Sass options documentation}.
|
153
155
|
#
|
154
156
|
# @return [Symbol]
|
155
157
|
def style
|
data/lib/sass/tree/prop_node.rb
CHANGED
@@ -39,7 +39,7 @@ module Sass::Tree
|
|
39
39
|
# * This is a child property of another property
|
40
40
|
# * The parent property has a value, and thus will be rendered
|
41
41
|
#
|
42
|
-
# @return [
|
42
|
+
# @return [Integer]
|
43
43
|
attr_accessor :tabs
|
44
44
|
|
45
45
|
# The source range in which the property name appears.
|
@@ -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")
|
@@ -119,11 +119,10 @@ module Sass::Tree
|
|
119
119
|
private
|
120
120
|
|
121
121
|
def check!
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
end
|
122
|
+
return unless @options[:property_syntax] && @options[:property_syntax] != @prop_syntax
|
123
|
+
raise Sass::SyntaxError.new(
|
124
|
+
"Illegal property syntax: can't use #{@prop_syntax} syntax when " +
|
125
|
+
":property_syntax => #{@options[:property_syntax].inspect} is set.")
|
127
126
|
end
|
128
127
|
|
129
128
|
class << self
|
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
|
@@ -40,7 +40,7 @@ module Sass::Tree
|
|
40
40
|
# * This is a child rule of another rule
|
41
41
|
# * The parent rule has properties, and thus will be rendered
|
42
42
|
#
|
43
|
-
# @return [
|
43
|
+
# @return [Integer]
|
44
44
|
attr_accessor :tabs
|
45
45
|
|
46
46
|
# The entire selector source range for this rule.
|
@@ -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
|
|
@@ -127,14 +132,24 @@ module Sass::Tree
|
|
127
132
|
private
|
128
133
|
|
129
134
|
def try_to_parse_non_interpolated_rules
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
135
|
+
@parsed_rules = nil
|
136
|
+
return unless @rule.all? {|t| t.is_a?(String)}
|
137
|
+
|
138
|
+
# We don't use real filename/line info because we don't have it yet.
|
139
|
+
# When we get it, we'll set it on the parsed rules if possible.
|
140
|
+
parser = nil
|
141
|
+
warnings = Sass::Util.silence_warnings do
|
142
|
+
parser = Sass::SCSS::StaticParser.new(@rule.join.strip, nil, nil, 1)
|
134
143
|
# rubocop:disable RescueModifier
|
135
144
|
@parsed_rules = parser.parse_selector rescue nil
|
136
145
|
# rubocop:enable RescueModifier
|
146
|
+
|
147
|
+
$stderr.string
|
137
148
|
end
|
149
|
+
|
150
|
+
# If parsing produces a warning, throw away the result so we can parse
|
151
|
+
# later with the real filename info.
|
152
|
+
@parsed_rules = nil unless warnings.empty?
|
138
153
|
end
|
139
154
|
end
|
140
155
|
end
|
@@ -4,6 +4,8 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
|
|
4
4
|
|
5
5
|
def initialize
|
6
6
|
@parents = []
|
7
|
+
@parent = nil
|
8
|
+
@current_mixin_def = nil
|
7
9
|
end
|
8
10
|
|
9
11
|
def visit(node)
|
@@ -23,13 +25,34 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
|
|
23
25
|
SCRIPT_NODES = [Sass::Tree::ImportNode] + CONTROL_NODES
|
24
26
|
def visit_children(parent)
|
25
27
|
old_parent = @parent
|
26
|
-
|
27
|
-
|
28
|
+
|
29
|
+
# When checking a static tree, resolve at-roots to be sure they won't send
|
30
|
+
# nodes where they don't belong.
|
31
|
+
if parent.is_a?(Sass::Tree::AtRootNode) && parent.resolved_value
|
32
|
+
old_parents = @parents
|
33
|
+
@parents = @parents.reject {|p| parent.exclude_node?(p)}
|
34
|
+
@parent = Sass::Util.enum_with_index(@parents.reverse).
|
35
|
+
find {|p, i| !transparent_parent?(p, @parents[-i - 2])}.first
|
36
|
+
|
37
|
+
begin
|
38
|
+
return super
|
39
|
+
ensure
|
40
|
+
@parents = old_parents
|
41
|
+
@parent = old_parent
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
unless transparent_parent?(parent, old_parent)
|
46
|
+
@parent = parent
|
47
|
+
end
|
48
|
+
|
28
49
|
@parents.push parent
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
50
|
+
begin
|
51
|
+
super
|
52
|
+
ensure
|
53
|
+
@parent = old_parent
|
54
|
+
@parents.pop
|
55
|
+
end
|
33
56
|
end
|
34
57
|
|
35
58
|
def visit_root(node)
|
@@ -69,9 +92,8 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
|
|
69
92
|
|
70
93
|
VALID_EXTEND_PARENTS = [Sass::Tree::RuleNode, Sass::Tree::MixinDefNode, Sass::Tree::MixinNode]
|
71
94
|
def invalid_extend_parent?(parent, child)
|
72
|
-
|
73
|
-
|
74
|
-
end
|
95
|
+
return if is_any_of?(parent, VALID_EXTEND_PARENTS)
|
96
|
+
"Extend directives may only be used within rules."
|
75
97
|
end
|
76
98
|
|
77
99
|
INVALID_IMPORT_PARENTS = CONTROL_NODES +
|
@@ -89,44 +111,38 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
|
|
89
111
|
end
|
90
112
|
|
91
113
|
def invalid_mixindef_parent?(parent, child)
|
92
|
-
|
93
|
-
|
94
|
-
end
|
114
|
+
return if (@parents.map {|p| p.class} & INVALID_IMPORT_PARENTS).empty?
|
115
|
+
"Mixins may not be defined within control directives or other mixins."
|
95
116
|
end
|
96
117
|
|
97
118
|
def invalid_function_parent?(parent, child)
|
98
|
-
|
99
|
-
|
100
|
-
end
|
119
|
+
return if (@parents.map {|p| p.class} & INVALID_IMPORT_PARENTS).empty?
|
120
|
+
"Functions may not be defined within control directives or other mixins."
|
101
121
|
end
|
102
122
|
|
103
123
|
VALID_FUNCTION_CHILDREN = [
|
104
124
|
Sass::Tree::CommentNode, Sass::Tree::DebugNode, Sass::Tree::ReturnNode,
|
105
|
-
Sass::Tree::VariableNode, Sass::Tree::WarnNode
|
125
|
+
Sass::Tree::VariableNode, Sass::Tree::WarnNode, Sass::Tree::ErrorNode
|
106
126
|
] + CONTROL_NODES
|
107
127
|
def invalid_function_child?(parent, child)
|
108
|
-
|
109
|
-
|
110
|
-
end
|
128
|
+
return if is_any_of?(child, VALID_FUNCTION_CHILDREN)
|
129
|
+
"Functions can only contain variable declarations and control directives."
|
111
130
|
end
|
112
131
|
|
113
|
-
VALID_PROP_CHILDREN =
|
114
|
-
|
115
|
-
|
132
|
+
VALID_PROP_CHILDREN = CONTROL_NODES + [Sass::Tree::CommentNode,
|
133
|
+
Sass::Tree::PropNode,
|
134
|
+
Sass::Tree::MixinNode]
|
116
135
|
def invalid_prop_child?(parent, child)
|
117
|
-
|
118
|
-
|
119
|
-
end
|
136
|
+
return if is_any_of?(child, VALID_PROP_CHILDREN)
|
137
|
+
"Illegal nesting: Only properties may be nested beneath properties."
|
120
138
|
end
|
121
139
|
|
122
|
-
VALID_PROP_PARENTS = [Sass::Tree::RuleNode, Sass::Tree::PropNode,
|
123
|
-
Sass::Tree::MixinDefNode, Sass::Tree::DirectiveNode,
|
124
|
-
Sass::Tree::MixinNode]
|
140
|
+
VALID_PROP_PARENTS = [Sass::Tree::RuleNode, Sass::Tree::KeyframeRuleNode, Sass::Tree::PropNode,
|
141
|
+
Sass::Tree::MixinDefNode, Sass::Tree::DirectiveNode, Sass::Tree::MixinNode]
|
125
142
|
def invalid_prop_parent?(parent, child)
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
end
|
143
|
+
return if is_any_of?(parent, VALID_PROP_PARENTS)
|
144
|
+
"Properties are only allowed within rules, directives, mixin includes, or other properties." +
|
145
|
+
child.pseudo_class_selector_message
|
130
146
|
end
|
131
147
|
|
132
148
|
def invalid_return_parent?(parent, child)
|
@@ -135,6 +151,14 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
|
|
135
151
|
|
136
152
|
private
|
137
153
|
|
154
|
+
# Whether `parent` should be assigned to `@parent`.
|
155
|
+
def transparent_parent?(parent, grandparent)
|
156
|
+
is_any_of?(parent, SCRIPT_NODES) ||
|
157
|
+
(parent.bubbles? &&
|
158
|
+
!grandparent.is_a?(Sass::Tree::RootNode) &&
|
159
|
+
!grandparent.is_a?(Sass::Tree::AtRootNode))
|
160
|
+
end
|
161
|
+
|
138
162
|
def is_any_of?(val, classes)
|
139
163
|
classes.each do |c|
|
140
164
|
return true if val.is_a?(c)
|
@@ -18,15 +18,19 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
18
18
|
@tabs = 0
|
19
19
|
# 2 spaces by default
|
20
20
|
@tab_chars = @options[:indent] || " "
|
21
|
+
@is_else = false
|
21
22
|
end
|
22
23
|
|
23
24
|
def visit_children(parent)
|
24
25
|
@tabs += 1
|
25
26
|
return @format == :sass ? "\n" : " {}\n" if parent.children.empty?
|
27
|
+
|
28
|
+
res = visit_rule_level(parent.children)
|
29
|
+
|
26
30
|
if @format == :sass
|
27
|
-
"\n"
|
31
|
+
"\n" + res.rstrip + "\n"
|
28
32
|
else
|
29
|
-
" {\n" +
|
33
|
+
" {\n" + res.rstrip + "\n#{@tab_chars * (@tabs - 1)}}\n"
|
30
34
|
end
|
31
35
|
ensure
|
32
36
|
@tabs -= 1
|
@@ -34,20 +38,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
34
38
|
|
35
39
|
# Ensures proper spacing between top-level nodes.
|
36
40
|
def visit_root(node)
|
37
|
-
|
38
|
-
visit(child) +
|
39
|
-
if nxt &&
|
40
|
-
(child.is_a?(Sass::Tree::CommentNode) &&
|
41
|
-
child.line + child.lines + 1 == nxt.line) ||
|
42
|
-
(child.is_a?(Sass::Tree::ImportNode) && nxt.is_a?(Sass::Tree::ImportNode) &&
|
43
|
-
child.line + 1 == nxt.line) ||
|
44
|
-
(child.is_a?(Sass::Tree::VariableNode) && nxt.is_a?(Sass::Tree::VariableNode) &&
|
45
|
-
child.line + 1 == nxt.line)
|
46
|
-
""
|
47
|
-
else
|
48
|
-
"\n"
|
49
|
-
end
|
50
|
-
end.join.rstrip + "\n"
|
41
|
+
visit_rule_level(node.children)
|
51
42
|
end
|
52
43
|
|
53
44
|
def visit_charset(node)
|
@@ -57,14 +48,14 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
57
48
|
def visit_comment(node)
|
58
49
|
value = interp_to_src(node.value)
|
59
50
|
if @format == :sass
|
60
|
-
content = value.gsub(
|
51
|
+
content = value.gsub(%r{\*/$}, '').rstrip
|
61
52
|
if content =~ /\A[ \t]/
|
62
53
|
# Re-indent SCSS comments like this:
|
63
54
|
# /* foo
|
64
55
|
# bar
|
65
56
|
# baz */
|
66
57
|
content.gsub!(/^/, ' ')
|
67
|
-
content.sub!(
|
58
|
+
content.sub!(%r{\A([ \t]*)/\*}, '/*\1')
|
68
59
|
end
|
69
60
|
|
70
61
|
if content.include?("\n")
|
@@ -78,13 +69,13 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
78
69
|
end
|
79
70
|
end
|
80
71
|
|
81
|
-
content.gsub!(
|
72
|
+
content.gsub!(%r{\A/\*}, '//') if node.type == :silent
|
82
73
|
content.gsub!(/^/, tab_str)
|
83
74
|
content = content.rstrip + "\n"
|
84
75
|
else
|
85
76
|
spaces = (@tab_chars * [@tabs - value[/^ */].size, 0].max)
|
86
77
|
content = if node.type == :silent
|
87
|
-
value.gsub(
|
78
|
+
value.gsub(%r{^[/ ]\*}, '//').gsub(%r{ *\*/$}, '')
|
88
79
|
else
|
89
80
|
value
|
90
81
|
end.gsub(/^/, spaces) + "\n"
|
@@ -96,11 +87,15 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
96
87
|
"#{tab_str}@debug #{node.expr.to_sass(@options)}#{semi}\n"
|
97
88
|
end
|
98
89
|
|
90
|
+
def visit_error(node)
|
91
|
+
"#{tab_str}@error #{node.expr.to_sass(@options)}#{semi}\n"
|
92
|
+
end
|
93
|
+
|
99
94
|
def visit_directive(node)
|
100
95
|
res = "#{tab_str}#{interp_to_src(node.value)}"
|
101
96
|
res.gsub!(/^@import \#\{(.*)\}([^}]*)$/, '@import \1\2')
|
102
97
|
return res + "#{semi}\n" unless node.has_children
|
103
|
-
res + yield
|
98
|
+
res + yield
|
104
99
|
end
|
105
100
|
|
106
101
|
def visit_each(node)
|
@@ -109,13 +104,13 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
109
104
|
end
|
110
105
|
|
111
106
|
def visit_extend(node)
|
112
|
-
"#{tab_str}@extend #{selector_to_src(node.selector).lstrip}
|
113
|
-
"#{
|
107
|
+
"#{tab_str}@extend #{selector_to_src(node.selector).lstrip}" +
|
108
|
+
"#{' !optional' if node.optional?}#{semi}\n"
|
114
109
|
end
|
115
110
|
|
116
111
|
def visit_for(node)
|
117
112
|
"#{tab_str}@for $#{dasherize(node.var)} from #{node.from.to_sass(@options)} " +
|
118
|
-
"#{node.exclusive ?
|
113
|
+
"#{node.exclusive ? 'to' : 'through'} #{node.to.to_sass(@options)}#{yield}"
|
119
114
|
end
|
120
115
|
|
121
116
|
def visit_function(node)
|
@@ -169,6 +164,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
169
164
|
else
|
170
165
|
str = "#{tab_str}@import #{node.uri}"
|
171
166
|
end
|
167
|
+
str << " supports(#{node.supports_condition.to_src(@options)})" if node.supports_condition
|
172
168
|
str << " #{interp_to_src(node.query)}" unless node.query.empty?
|
173
169
|
"#{str}#{semi}\n"
|
174
170
|
end
|
@@ -236,12 +232,13 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
236
232
|
end
|
237
233
|
|
238
234
|
def visit_rule(node)
|
235
|
+
rule = node.parsed_rules ? [node.parsed_rules.to_s] : node.rule
|
239
236
|
if @format == :sass
|
240
|
-
name = selector_to_sass(
|
237
|
+
name = selector_to_sass(rule)
|
241
238
|
name = "\\" + name if name[0] == ?:
|
242
239
|
name.gsub(/^/, tab_str) + yield
|
243
240
|
elsif @format == :scss
|
244
|
-
name = selector_to_scss(
|
241
|
+
name = selector_to_scss(rule)
|
245
242
|
res = name + yield
|
246
243
|
if node.children.last.is_a?(Sass::Tree::CommentNode) && node.children.last.type == :silent
|
247
244
|
res.slice!(-3..-1)
|
@@ -269,35 +266,53 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
269
266
|
"#{tab_str}@at-root #{query_interp_to_src(node.query)}#{yield}"
|
270
267
|
elsif node.children.length == 1 && node.children.first.is_a?(Sass::Tree::RuleNode)
|
271
268
|
rule = node.children.first
|
272
|
-
"#{tab_str}@at-root #{selector_to_src(rule.rule)}#{visit_children(rule)}"
|
269
|
+
"#{tab_str}@at-root #{selector_to_src(rule.rule).lstrip}#{visit_children(rule)}"
|
273
270
|
else
|
274
271
|
"#{tab_str}@at-root#{yield}"
|
275
272
|
end
|
276
273
|
end
|
277
274
|
|
275
|
+
def visit_keyframerule(node)
|
276
|
+
"#{tab_str}#{node.resolved_value}#{yield}"
|
277
|
+
end
|
278
|
+
|
278
279
|
private
|
279
280
|
|
281
|
+
# Visit rule-level nodes and return their conversion with appropriate
|
282
|
+
# whitespace added.
|
283
|
+
def visit_rule_level(nodes)
|
284
|
+
Sass::Util.enum_cons(nodes + [nil], 2).map do |child, nxt|
|
285
|
+
visit(child) +
|
286
|
+
if nxt &&
|
287
|
+
(child.is_a?(Sass::Tree::CommentNode) && child.line + child.lines + 1 == nxt.line) ||
|
288
|
+
(child.is_a?(Sass::Tree::ImportNode) && nxt.is_a?(Sass::Tree::ImportNode) &&
|
289
|
+
child.line + 1 == nxt.line) ||
|
290
|
+
(child.is_a?(Sass::Tree::VariableNode) && nxt.is_a?(Sass::Tree::VariableNode) &&
|
291
|
+
child.line + 1 == nxt.line) ||
|
292
|
+
(child.is_a?(Sass::Tree::PropNode) && nxt.is_a?(Sass::Tree::PropNode)) ||
|
293
|
+
(child.is_a?(Sass::Tree::MixinNode) && nxt.is_a?(Sass::Tree::MixinNode) &&
|
294
|
+
child.line + 1 == nxt.line)
|
295
|
+
""
|
296
|
+
else
|
297
|
+
"\n"
|
298
|
+
end
|
299
|
+
end.join.rstrip + "\n"
|
300
|
+
end
|
301
|
+
|
280
302
|
def interp_to_src(interp)
|
281
|
-
interp.map
|
282
|
-
next r if r.is_a?(String)
|
283
|
-
"\#{#{r.to_sass(@options)}}"
|
284
|
-
end.join
|
303
|
+
interp.map {|r| r.is_a?(String) ? r : r.to_sass(@options)}.join
|
285
304
|
end
|
286
305
|
|
287
306
|
# Like interp_to_src, but removes the unnecessary `#{}` around the keys and
|
288
307
|
# values in query expressions.
|
289
308
|
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
|
309
|
+
interp = interp.map do |e|
|
310
|
+
next e unless e.is_a?(Sass::Script::Tree::Literal)
|
311
|
+
next e unless e.value.is_a?(Sass::Script::Value::String)
|
312
|
+
e.value.value
|
313
|
+
end
|
314
|
+
|
315
|
+
interp_to_src(interp)
|
301
316
|
end
|
302
317
|
|
303
318
|
def selector_to_src(sel)
|
@@ -309,7 +324,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
309
324
|
if r.is_a?(String)
|
310
325
|
r.gsub(/(,)?([ \t]*)\n\s*/) {$1 ? "#{$1}#{$2}\n" : " "}
|
311
326
|
else
|
312
|
-
|
327
|
+
r.to_sass(@options)
|
313
328
|
end
|
314
329
|
end.join
|
315
330
|
end
|
@@ -328,7 +343,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
328
343
|
|
329
344
|
def dasherize(s)
|
330
345
|
if @options[:dasherize]
|
331
|
-
s.
|
346
|
+
s.tr('_', '-')
|
332
347
|
else
|
333
348
|
s
|
334
349
|
end
|