sass 3.7.4 → 4.0.0.alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +13 -5
- data/.yardopts +1 -1
- data/CODE_OF_CONDUCT.md +1 -1
- data/CONTRIBUTING.md +1 -146
- data/MIT-LICENSE +1 -1
- data/README.md +25 -39
- data/Rakefile +274 -0
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/lib/sass.rb +3 -3
- data/lib/sass/cache_stores/filesystem.rb +2 -2
- data/lib/sass/cache_stores/memory.rb +5 -4
- data/lib/sass/callbacks.rb +2 -2
- data/lib/sass/css.rb +12 -12
- data/lib/sass/engine.rb +44 -62
- data/lib/sass/environment.rb +7 -35
- data/lib/sass/error.rb +14 -14
- data/lib/sass/exec/base.rb +14 -3
- data/lib/sass/exec/sass_convert.rb +6 -20
- data/lib/sass/exec/sass_scss.rb +29 -5
- data/lib/sass/features.rb +2 -3
- data/lib/sass/importers/filesystem.rb +6 -11
- data/lib/sass/logger.rb +3 -8
- data/lib/sass/logger/base.rb +2 -19
- data/lib/sass/plugin.rb +2 -3
- data/lib/sass/plugin/compiler.rb +67 -48
- data/lib/sass/plugin/configuration.rb +3 -3
- data/lib/sass/plugin/merb.rb +1 -1
- data/lib/sass/plugin/rack.rb +3 -3
- data/lib/sass/plugin/staleness_checker.rb +3 -3
- data/lib/sass/railtie.rb +1 -1
- data/lib/sass/script.rb +3 -3
- data/lib/sass/script/css_parser.rb +15 -5
- data/lib/sass/script/functions.rb +121 -337
- data/lib/sass/script/lexer.rb +36 -102
- data/lib/sass/script/parser.rb +153 -529
- data/lib/sass/script/tree/funcall.rb +34 -42
- data/lib/sass/script/tree/interpolation.rb +26 -171
- data/lib/sass/script/tree/list_literal.rb +8 -23
- data/lib/sass/script/tree/map_literal.rb +2 -2
- data/lib/sass/script/tree/node.rb +3 -3
- data/lib/sass/script/tree/operation.rb +16 -43
- data/lib/sass/script/tree/string_interpolation.rb +43 -64
- data/lib/sass/script/tree/variable.rb +1 -1
- data/lib/sass/script/value.rb +0 -2
- data/lib/sass/script/value/arg_list.rb +1 -1
- data/lib/sass/script/value/base.rb +9 -27
- data/lib/sass/script/value/color.rb +18 -26
- data/lib/sass/script/value/helpers.rb +18 -44
- data/lib/sass/script/value/list.rb +14 -35
- data/lib/sass/script/value/map.rb +2 -2
- data/lib/sass/script/value/number.rb +16 -26
- data/lib/sass/script/value/string.rb +1 -30
- data/lib/sass/scss.rb +2 -0
- data/lib/sass/scss/css_parser.rb +3 -7
- data/lib/sass/scss/parser.rb +78 -196
- data/lib/sass/scss/rx.rb +14 -7
- data/lib/sass/scss/script_lexer.rb +15 -0
- data/lib/sass/scss/script_parser.rb +25 -0
- data/lib/sass/scss/static_parser.rb +55 -38
- data/lib/sass/selector.rb +10 -7
- data/lib/sass/selector/abstract_sequence.rb +12 -15
- data/lib/sass/selector/comma_sequence.rb +6 -24
- data/lib/sass/selector/pseudo.rb +6 -19
- data/lib/sass/selector/sequence.rb +16 -14
- data/lib/sass/selector/simple.rb +7 -9
- data/lib/sass/selector/simple_sequence.rb +12 -16
- data/lib/sass/shared.rb +1 -1
- data/lib/sass/source/map.rb +9 -7
- data/lib/sass/source/position.rb +4 -4
- data/lib/sass/stack.rb +3 -23
- data/lib/sass/tree/charset_node.rb +1 -1
- data/lib/sass/tree/comment_node.rb +1 -1
- data/lib/sass/tree/function_node.rb +3 -2
- data/lib/sass/tree/node.rb +3 -5
- data/lib/sass/tree/prop_node.rb +58 -49
- data/lib/sass/tree/rule_node.rb +8 -15
- data/lib/sass/tree/visitors/check_nesting.rb +23 -19
- data/lib/sass/tree/visitors/convert.rb +13 -15
- data/lib/sass/tree/visitors/cssize.rb +15 -4
- data/lib/sass/tree/visitors/deep_copy.rb +2 -2
- data/lib/sass/tree/visitors/extend.rb +14 -10
- data/lib/sass/tree/visitors/perform.rb +18 -29
- data/lib/sass/tree/visitors/set_options.rb +2 -2
- data/lib/sass/tree/visitors/to_css.rb +47 -77
- data/lib/sass/util.rb +311 -98
- data/lib/sass/util/cross_platform_random.rb +19 -0
- data/lib/sass/util/multibyte_string_scanner.rb +133 -127
- data/lib/sass/util/normalized_map.rb +8 -1
- data/lib/sass/util/ordered_hash.rb +192 -0
- data/lib/sass/version.rb +6 -2
- data/test/sass/cache_test.rb +131 -0
- data/test/sass/callbacks_test.rb +61 -0
- data/test/sass/compiler_test.rb +236 -0
- data/test/sass/conversion_test.rb +2171 -0
- data/test/sass/css2sass_test.rb +526 -0
- data/test/sass/data/hsl-rgb.txt +319 -0
- data/test/sass/encoding_test.rb +219 -0
- data/test/sass/engine_test.rb +3400 -0
- data/test/sass/exec_test.rb +86 -0
- data/test/sass/extend_test.rb +1719 -0
- data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
- data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
- data/test/sass/functions_test.rb +1984 -0
- data/test/sass/importer_test.rb +421 -0
- data/test/sass/logger_test.rb +58 -0
- data/test/sass/mock_importer.rb +49 -0
- data/test/sass/more_results/more1.css +9 -0
- data/test/sass/more_results/more1_with_line_comments.css +26 -0
- data/test/sass/more_results/more_import.css +29 -0
- data/test/sass/more_templates/_more_partial.sass +2 -0
- data/test/sass/more_templates/more1.sass +23 -0
- data/test/sass/more_templates/more_import.sass +11 -0
- data/test/sass/plugin_test.rb +556 -0
- data/test/sass/results/alt.css +4 -0
- data/test/sass/results/basic.css +9 -0
- data/test/sass/results/cached_import_option.css +3 -0
- data/test/sass/results/compact.css +5 -0
- data/test/sass/results/complex.css +86 -0
- data/test/sass/results/compressed.css +1 -0
- data/test/sass/results/expanded.css +19 -0
- data/test/sass/results/filename_fn.css +3 -0
- data/test/sass/results/if.css +3 -0
- data/test/sass/results/import.css +31 -0
- data/test/sass/results/import_charset.css +5 -0
- data/test/sass/results/import_charset_1_8.css +5 -0
- data/test/sass/results/import_charset_ibm866.css +5 -0
- data/test/sass/results/import_content.css +1 -0
- data/test/sass/results/line_numbers.css +49 -0
- data/test/sass/results/mixins.css +95 -0
- data/test/sass/results/multiline.css +24 -0
- data/test/sass/results/nested.css +22 -0
- data/test/sass/results/options.css +1 -0
- data/test/sass/results/parent_ref.css +13 -0
- data/test/sass/results/script.css +16 -0
- data/test/sass/results/scss_import.css +31 -0
- data/test/sass/results/scss_importee.css +2 -0
- data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
- data/test/sass/results/subdir/subdir.css +3 -0
- data/test/sass/results/units.css +11 -0
- data/test/sass/results/warn.css +0 -0
- data/test/sass/results/warn_imported.css +0 -0
- data/test/sass/script_conversion_test.rb +306 -0
- data/test/sass/script_test.rb +1206 -0
- data/test/sass/scss/css_test.rb +1281 -0
- data/test/sass/scss/rx_test.rb +160 -0
- data/test/sass/scss/scss_test.rb +4147 -0
- data/test/sass/scss/test_helper.rb +37 -0
- data/test/sass/source_map_test.rb +1055 -0
- data/test/sass/superselector_test.rb +210 -0
- data/test/sass/templates/_cached_import_option_partial.scss +1 -0
- data/test/sass/templates/_double_import_loop2.sass +1 -0
- data/test/sass/templates/_filename_fn_import.scss +11 -0
- data/test/sass/templates/_imported_charset_ibm866.sass +4 -0
- data/test/sass/templates/_imported_charset_utf8.sass +4 -0
- data/test/sass/templates/_imported_content.sass +3 -0
- data/test/sass/templates/_partial.sass +2 -0
- data/test/sass/templates/_same_name_different_partiality.scss +1 -0
- data/test/sass/templates/alt.sass +16 -0
- data/test/sass/templates/basic.sass +23 -0
- data/test/sass/templates/bork1.sass +2 -0
- data/test/sass/templates/bork2.sass +2 -0
- data/test/sass/templates/bork3.sass +2 -0
- data/test/sass/templates/bork4.sass +2 -0
- data/test/sass/templates/bork5.sass +3 -0
- data/test/sass/templates/cached_import_option.scss +3 -0
- data/test/sass/templates/compact.sass +17 -0
- data/test/sass/templates/complex.sass +305 -0
- data/test/sass/templates/compressed.sass +15 -0
- data/test/sass/templates/double_import_loop1.sass +1 -0
- data/test/sass/templates/expanded.sass +17 -0
- data/test/sass/templates/filename_fn.scss +18 -0
- data/test/sass/templates/if.sass +11 -0
- data/test/sass/templates/import.sass +12 -0
- data/test/sass/templates/import_charset.sass +9 -0
- data/test/sass/templates/import_charset_1_8.sass +6 -0
- data/test/sass/templates/import_charset_ibm866.sass +11 -0
- data/test/sass/templates/import_content.sass +4 -0
- data/test/sass/templates/importee.less +2 -0
- data/test/sass/templates/importee.sass +19 -0
- data/test/sass/templates/line_numbers.sass +13 -0
- data/test/sass/templates/mixin_bork.sass +5 -0
- data/test/sass/templates/mixins.sass +76 -0
- data/test/sass/templates/multiline.sass +20 -0
- data/test/sass/templates/nested.sass +25 -0
- data/test/sass/templates/nested_bork1.sass +2 -0
- data/test/sass/templates/nested_bork2.sass +2 -0
- data/test/sass/templates/nested_bork3.sass +2 -0
- data/test/sass/templates/nested_bork4.sass +2 -0
- data/test/sass/templates/nested_import.sass +2 -0
- data/test/sass/templates/nested_mixin_bork.sass +6 -0
- data/test/sass/templates/options.sass +2 -0
- data/test/sass/templates/parent_ref.sass +25 -0
- data/test/sass/templates/same_name_different_ext.sass +2 -0
- data/test/sass/templates/same_name_different_ext.scss +1 -0
- data/test/sass/templates/same_name_different_partiality.scss +1 -0
- data/test/sass/templates/script.sass +101 -0
- data/test/sass/templates/scss_import.scss +12 -0
- data/test/sass/templates/scss_importee.scss +1 -0
- data/test/sass/templates/single_import_loop.sass +1 -0
- data/test/sass/templates/subdir/import_up1.scss +1 -0
- data/test/sass/templates/subdir/import_up2.scss +1 -0
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
- data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
- data/test/sass/templates/subdir/subdir.sass +6 -0
- data/test/sass/templates/units.sass +11 -0
- data/test/sass/templates/warn.sass +3 -0
- data/test/sass/templates/warn_imported.sass +4 -0
- data/test/sass/test_helper.rb +8 -0
- data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
- data/test/sass/util/normalized_map_test.rb +51 -0
- data/test/sass/util/subset_map_test.rb +91 -0
- data/test/sass/util_test.rb +438 -0
- data/test/sass/value_helpers_test.rb +179 -0
- data/test/test_helper.rb +110 -0
- data/vendor/listen/CHANGELOG.md +1 -0
- data/vendor/listen/CONTRIBUTING.md +38 -0
- data/vendor/listen/Gemfile +20 -0
- data/vendor/listen/Guardfile +8 -0
- data/vendor/listen/LICENSE +20 -0
- data/vendor/listen/README.md +349 -0
- data/vendor/listen/Rakefile +5 -0
- data/vendor/listen/Vagrantfile +96 -0
- data/vendor/listen/lib/listen.rb +54 -0
- data/vendor/listen/lib/listen/adapter.rb +327 -0
- data/vendor/listen/lib/listen/adapters/bsd.rb +75 -0
- data/vendor/listen/lib/listen/adapters/darwin.rb +48 -0
- data/vendor/listen/lib/listen/adapters/linux.rb +81 -0
- data/vendor/listen/lib/listen/adapters/polling.rb +58 -0
- data/vendor/listen/lib/listen/adapters/windows.rb +91 -0
- data/vendor/listen/lib/listen/directory_record.rb +406 -0
- data/vendor/listen/lib/listen/listener.rb +323 -0
- data/vendor/listen/lib/listen/turnstile.rb +32 -0
- data/vendor/listen/lib/listen/version.rb +3 -0
- data/vendor/listen/listen.gemspec +28 -0
- data/vendor/listen/spec/listen/adapter_spec.rb +149 -0
- data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
- data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
- data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
- data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
- data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
- data/vendor/listen/spec/listen/directory_record_spec.rb +1250 -0
- data/vendor/listen/spec/listen/listener_spec.rb +258 -0
- data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
- data/vendor/listen/spec/listen_spec.rb +67 -0
- data/vendor/listen/spec/spec_helper.rb +25 -0
- data/vendor/listen/spec/support/adapter_helper.rb +666 -0
- data/vendor/listen/spec/support/directory_record_helper.rb +57 -0
- data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
- data/vendor/listen/spec/support/listeners_helper.rb +179 -0
- data/vendor/listen/spec/support/platform_helper.rb +15 -0
- metadata +217 -76
- data/extra/sass-spec-ref.sh +0 -40
- data/lib/sass/deprecation.rb +0 -55
- data/lib/sass/logger/delayed.rb +0 -50
- data/lib/sass/script/value/callable.rb +0 -25
- data/lib/sass/script/value/function.rb +0 -19
@@ -66,35 +66,26 @@ module Sass::Script::Value
|
|
66
66
|
Number.new(number, *parse_unit_string(unit_string))
|
67
67
|
end
|
68
68
|
|
69
|
-
# @overload list(*elements, separator
|
69
|
+
# @overload list(*elements, separator)
|
70
70
|
# Create a space-separated list from the arguments given.
|
71
71
|
# @param elements [Array<Sass::Script::Value::Base>] Each argument will be a list element.
|
72
72
|
# @param separator [Symbol] Either :space or :comma.
|
73
|
-
# @param bracketed [Boolean] Whether the list uses square brackets.
|
74
73
|
# @return [Sass::Script::Value::List] The space separated list.
|
75
74
|
#
|
76
|
-
# @overload list(array, separator
|
75
|
+
# @overload list(array, separator)
|
77
76
|
# Create a space-separated list from the array given.
|
78
77
|
# @param array [Array<Sass::Script::Value::Base>] A ruby array of Sass values
|
79
78
|
# to make into a list.
|
80
|
-
# @param separator [Symbol] Either :space or :comma.
|
81
|
-
# @param bracketed [Boolean] Whether the list uses square brackets.
|
82
79
|
# @return [Sass::Script::Value::List] The space separated list.
|
83
|
-
def list(*elements
|
84
|
-
|
85
|
-
|
86
|
-
if separator.nil?
|
87
|
-
if elements.last.is_a?(Symbol)
|
88
|
-
separator = elements.pop
|
89
|
-
else
|
90
|
-
raise ArgumentError.new("A separator of :space or :comma must be specified.")
|
91
|
-
end
|
80
|
+
def list(*elements)
|
81
|
+
unless elements.last.is_a?(Symbol)
|
82
|
+
raise ArgumentError.new("A list type of :space or :comma must be specified.")
|
92
83
|
end
|
93
|
-
|
84
|
+
separator = elements.pop
|
94
85
|
if elements.size == 1 && elements.first.is_a?(Array)
|
95
86
|
elements = elements.first
|
96
87
|
end
|
97
|
-
Sass::Script::Value::List.new(elements, separator
|
88
|
+
Sass::Script::Value::List.new(elements, separator)
|
98
89
|
end
|
99
90
|
|
100
91
|
# Construct a Sass map.
|
@@ -148,7 +139,7 @@ module Sass::Script::Value
|
|
148
139
|
Sass::SCSS::StaticParser.new(str, nil, nil, 1, 1, allow_parent_ref).parse_selector
|
149
140
|
rescue Sass::SyntaxError => e
|
150
141
|
err = "#{value.inspect} is not a valid selector: #{e}"
|
151
|
-
err = "$#{name.to_s.
|
142
|
+
err = "$#{name.to_s.gsub('_', '-')}: #{err}" if name
|
152
143
|
raise ArgumentError.new(err)
|
153
144
|
end
|
154
145
|
end
|
@@ -172,7 +163,7 @@ module Sass::Script::Value
|
|
172
163
|
return seq if selector.members.length == 1
|
173
164
|
|
174
165
|
err = "#{value.inspect} is not a complex selector"
|
175
|
-
err = "$#{name.to_s.
|
166
|
+
err = "$#{name.to_s.gsub('_', '-')}: #{err}" if name
|
176
167
|
raise ArgumentError.new(err)
|
177
168
|
end
|
178
169
|
|
@@ -199,35 +190,18 @@ module Sass::Script::Value
|
|
199
190
|
end
|
200
191
|
|
201
192
|
err = "#{value.inspect} is not a compound selector"
|
202
|
-
err = "$#{name.to_s.
|
193
|
+
err = "$#{name.to_s.gsub('_', '-')}: #{err}" if name
|
203
194
|
raise ArgumentError.new(err)
|
204
195
|
end
|
205
196
|
|
206
|
-
# Returns true when the literal is a string containing a calc()
|
207
|
-
#
|
208
|
-
# Use \{#special_number?} in preference to this.
|
197
|
+
# Returns true when the literal is a string containing a calc()
|
209
198
|
#
|
210
199
|
# @param literal [Sass::Script::Value::Base] The value to check
|
211
|
-
# @return
|
200
|
+
# @return boolean
|
212
201
|
def calc?(literal)
|
213
|
-
literal.is_a?(Sass::Script::Value::String)
|
214
|
-
|
215
|
-
|
216
|
-
# Returns true when the literal is a string containing a var().
|
217
|
-
#
|
218
|
-
# @param literal [Sass::Script::Value::Base] The value to check
|
219
|
-
# @return Boolean
|
220
|
-
def var?(literal)
|
221
|
-
literal.is_a?(Sass::Script::Value::String) && literal.value =~ /var\(/
|
222
|
-
end
|
223
|
-
|
224
|
-
# Returns whether the literal is a special CSS value that may evaluate to a
|
225
|
-
# number, such as `calc()` or `var()`.
|
226
|
-
#
|
227
|
-
# @param literal [Sass::Script::Value::Base] The value to check
|
228
|
-
# @return Boolean
|
229
|
-
def special_number?(literal)
|
230
|
-
literal.is_a?(Sass::Script::Value::String) && literal.value =~ /(calc|var)\(/
|
202
|
+
if literal.is_a?(Sass::Script::Value::String)
|
203
|
+
literal.value =~ /calc\(/
|
204
|
+
end
|
231
205
|
end
|
232
206
|
|
233
207
|
private
|
@@ -241,7 +215,7 @@ module Sass::Script::Value
|
|
241
215
|
|
242
216
|
err = "#{value.inspect} is not a valid selector: it must be a string,\n" +
|
243
217
|
"a list of strings, or a list of lists of strings"
|
244
|
-
err = "$#{name.to_s.
|
218
|
+
err = "$#{name.to_s.gsub('_', '-')}: #{err}" if name
|
245
219
|
raise ArgumentError.new(err)
|
246
220
|
end
|
247
221
|
|
@@ -278,14 +252,14 @@ module Sass::Script::Value
|
|
278
252
|
def parse_unit_string(unit_string)
|
279
253
|
denominator_units = numerator_units = Sass::Script::Value::Number::NO_UNITS
|
280
254
|
return numerator_units, denominator_units unless unit_string && unit_string.length > 0
|
281
|
-
num_over_denominator = unit_string.split(
|
255
|
+
num_over_denominator = unit_string.split(/ *\/ */)
|
282
256
|
unless (1..2).include?(num_over_denominator.size)
|
283
257
|
raise ArgumentError.new("Malformed unit string: #{unit_string}")
|
284
258
|
end
|
285
259
|
numerator_units = num_over_denominator[0].split(/ *\* */)
|
286
260
|
denominator_units = (num_over_denominator[1] || "").split(/ *\* */)
|
287
261
|
[[numerator_units, "numerator"], [denominator_units, "denominator"]].each do |units, name|
|
288
|
-
if unit_string =~
|
262
|
+
if unit_string =~ /\// && units.size == 0
|
289
263
|
raise ArgumentError.new("Malformed unit string: #{unit_string}")
|
290
264
|
end
|
291
265
|
if units.any? {|unit| unit !~ VALID_UNIT}
|
@@ -14,20 +14,13 @@ module Sass::Script::Value
|
|
14
14
|
# @return [Symbol]
|
15
15
|
attr_reader :separator
|
16
16
|
|
17
|
-
# Whether the list is surrounded by square brackets.
|
18
|
-
#
|
19
|
-
# @return [Boolean]
|
20
|
-
attr_reader :bracketed
|
21
|
-
|
22
17
|
# Creates a new list.
|
23
18
|
#
|
24
19
|
# @param value [Array<Value>] See \{#value}
|
25
20
|
# @param separator [Symbol] See \{#separator}
|
26
|
-
|
27
|
-
def initialize(value, separator: nil, bracketed: false)
|
21
|
+
def initialize(value, separator)
|
28
22
|
super(value)
|
29
23
|
@separator = separator
|
30
|
-
@bracketed = bracketed
|
31
24
|
end
|
32
25
|
|
33
26
|
# @see Value#options=
|
@@ -40,30 +33,24 @@ module Sass::Script::Value
|
|
40
33
|
def eq(other)
|
41
34
|
Sass::Script::Value::Bool.new(
|
42
35
|
other.is_a?(List) && value == other.value &&
|
43
|
-
separator == other.separator
|
36
|
+
separator == other.separator)
|
44
37
|
end
|
45
38
|
|
46
39
|
def hash
|
47
|
-
@hash ||= [value, separator
|
40
|
+
@hash ||= [value, separator].hash
|
48
41
|
end
|
49
42
|
|
50
43
|
# @see Value#to_s
|
51
44
|
def to_s(opts = {})
|
52
|
-
|
53
|
-
|
54
|
-
end
|
55
|
-
|
56
|
-
members = value.
|
45
|
+
raise Sass::SyntaxError.new("() isn't a valid CSS value.") if value.empty?
|
46
|
+
value.
|
57
47
|
reject {|e| e.is_a?(Null) || e.is_a?(List) && e.value.empty?}.
|
58
|
-
map {|e| e.to_s(opts)}
|
59
|
-
|
60
|
-
contents = members.join(sep_str)
|
61
|
-
bracketed ? "[#{contents}]" : contents
|
48
|
+
map {|e| e.to_s(opts)}.join(sep_str)
|
62
49
|
end
|
63
50
|
|
64
51
|
# @see Value#to_sass
|
65
52
|
def to_sass(opts = {})
|
66
|
-
return
|
53
|
+
return "()" if value.empty?
|
67
54
|
members = value.map do |v|
|
68
55
|
if element_needs_parens?(v)
|
69
56
|
"(#{v.to_sass(opts)})"
|
@@ -71,26 +58,19 @@ module Sass::Script::Value
|
|
71
58
|
v.to_sass(opts)
|
72
59
|
end
|
73
60
|
end
|
74
|
-
|
75
|
-
|
76
|
-
return "#{bracketed ? '[' : '('}#{members.first},#{bracketed ? ']' : ')'}"
|
77
|
-
end
|
78
|
-
|
79
|
-
contents = members.join(sep_str(nil))
|
80
|
-
bracketed ? "[#{contents}]" : contents
|
61
|
+
return "(#{members.first},)" if members.length == 1 && separator == :comma
|
62
|
+
members.join(sep_str(nil))
|
81
63
|
end
|
82
64
|
|
83
65
|
# @see Value#to_h
|
84
66
|
def to_h
|
85
|
-
return
|
67
|
+
return Sass::Util.ordered_hash if value.empty?
|
86
68
|
super
|
87
69
|
end
|
88
70
|
|
89
71
|
# @see Value#inspect
|
90
72
|
def inspect
|
91
|
-
(
|
92
|
-
value.map {|e| e.inspect}.join(sep_str(nil)) +
|
93
|
-
(bracketed ? ']' : ')')
|
73
|
+
"(#{value.map {|e| e.inspect}.join(sep_str(nil))})"
|
94
74
|
end
|
95
75
|
|
96
76
|
# Asserts an index is within the list.
|
@@ -114,10 +94,9 @@ module Sass::Script::Value
|
|
114
94
|
|
115
95
|
def element_needs_parens?(element)
|
116
96
|
if element.is_a?(List)
|
117
|
-
return false if element.value.
|
118
|
-
|
119
|
-
|
120
|
-
return Sass::Script::Parser.precedence_of(element.separator || :space) <= precedence
|
97
|
+
return false if element.value.empty?
|
98
|
+
precedence = Sass::Script::Parser.precedence_of(separator)
|
99
|
+
return Sass::Script::Parser.precedence_of(element.separator) <= precedence
|
121
100
|
end
|
122
101
|
|
123
102
|
return false unless separator == :space
|
@@ -12,7 +12,7 @@ module Sass::Script::Value
|
|
12
12
|
#
|
13
13
|
# @param hash [Hash<Node, Node>]
|
14
14
|
def initialize(hash)
|
15
|
-
super(hash)
|
15
|
+
super(Sass::Util.ordered_hash(hash))
|
16
16
|
end
|
17
17
|
|
18
18
|
# @see Value#options=
|
@@ -32,7 +32,7 @@ module Sass::Script::Value
|
|
32
32
|
# @see Value#to_a
|
33
33
|
def to_a
|
34
34
|
value.map do |k, v|
|
35
|
-
list = List.new([k, v],
|
35
|
+
list = List.new([k, v], :space)
|
36
36
|
list.options = options
|
37
37
|
list
|
38
38
|
end
|
@@ -34,35 +34,33 @@ module Sass::Script::Value
|
|
34
34
|
attr_accessor :original
|
35
35
|
|
36
36
|
def self.precision
|
37
|
-
|
37
|
+
@precision ||= 5
|
38
38
|
end
|
39
39
|
|
40
40
|
# Sets the number of digits of precision
|
41
41
|
# For example, if this is `3`,
|
42
42
|
# `3.1415926` will be printed as `3.142`.
|
43
|
-
# The numeric precision is stored as a thread local for thread safety reasons.
|
44
|
-
# To set for all threads, be sure to set the precision on the main thread.
|
45
43
|
def self.precision=(digits)
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
@precision = digits.round
|
45
|
+
@precision_factor = 10.0**@precision
|
46
|
+
@epsilon = 1 / (@precision_factor * 10)
|
49
47
|
end
|
50
48
|
|
51
49
|
# the precision factor used in numeric output
|
52
50
|
# it is derived from the `precision` method.
|
53
51
|
def self.precision_factor
|
54
|
-
|
52
|
+
@precision_factor ||= 10.0**precision
|
55
53
|
end
|
56
54
|
|
57
55
|
# Used in checking equality of floating point numbers. Any
|
58
56
|
# numbers within an `epsilon` of each other are considered functionally equal.
|
59
57
|
# The value for epsilon is one tenth of the current numeric precision.
|
60
58
|
def self.epsilon
|
61
|
-
|
59
|
+
@epsilon ||= 1 / (precision_factor * 10)
|
62
60
|
end
|
63
61
|
|
64
62
|
# Used so we don't allocate two new arrays for each new number.
|
65
|
-
NO_UNITS
|
63
|
+
NO_UNITS = []
|
66
64
|
|
67
65
|
# @param value [Numeric] The value of the number
|
68
66
|
# @param numerator_units [::String, Array<::String>] See \{#numerator\_units}
|
@@ -73,7 +71,6 @@ module Sass::Script::Value
|
|
73
71
|
super(value)
|
74
72
|
@numerator_units = numerator_units
|
75
73
|
@denominator_units = denominator_units
|
76
|
-
@options = nil
|
77
74
|
normalize!
|
78
75
|
end
|
79
76
|
|
@@ -189,7 +186,6 @@ module Sass::Script::Value
|
|
189
186
|
# @raise [Sass::UnitConversionError] if `other` has incompatible units
|
190
187
|
def mod(other)
|
191
188
|
if other.is_a?(Number)
|
192
|
-
return Number.new(Float::NAN) if other.value == 0
|
193
189
|
operate(other, :%)
|
194
190
|
else
|
195
191
|
raise NoMethodError.new(nil, :mod)
|
@@ -293,21 +289,14 @@ module Sass::Script::Value
|
|
293
289
|
# and confusing.
|
294
290
|
str = ("%0.#{self.class.precision}f" % value).gsub(/0*$/, '') if str.include?('e')
|
295
291
|
|
296
|
-
# Sometimes numeric formatting will result in a decimal number with a trailing zero (x.0)
|
297
|
-
if str =~ /(.*)\.0$/
|
298
|
-
str = $1
|
299
|
-
end
|
300
|
-
|
301
|
-
# We omit a leading zero before the decimal point in compressed mode.
|
302
292
|
if @options && options[:style] == :compressed
|
303
293
|
str.sub!(/^(-)?0\./, '\1.')
|
304
294
|
end
|
305
|
-
|
306
295
|
unitless? ? str : "#{str}#{unit_str}"
|
307
296
|
end
|
308
297
|
alias_method :to_sass, :inspect
|
309
298
|
|
310
|
-
# @return [
|
299
|
+
# @return [Fixnum] The integer value of the number
|
311
300
|
# @raise [Sass::SyntaxError] if the number isn't an integer
|
312
301
|
def to_i
|
313
302
|
super unless int?
|
@@ -414,7 +403,7 @@ module Sass::Script::Value
|
|
414
403
|
if num.is_a?(Float) && (num.infinite? || num.nan?)
|
415
404
|
num
|
416
405
|
elsif basically_equal?(num % 1, 0.0)
|
417
|
-
num.
|
406
|
+
num.to_i
|
418
407
|
else
|
419
408
|
((num * precision_factor).round / precision_factor).to_f
|
420
409
|
end
|
@@ -473,10 +462,11 @@ module Sass::Script::Value
|
|
473
462
|
sans_common_units(@numerator_units, @denominator_units)
|
474
463
|
|
475
464
|
@denominator_units.each_with_index do |d, i|
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
465
|
+
if convertable?(d) && (u = @numerator_units.find(&method(:convertable?)))
|
466
|
+
@value /= conversion_factor(d, u)
|
467
|
+
@denominator_units.delete_at(i)
|
468
|
+
@numerator_units.delete_at(@numerator_units.index(u))
|
469
|
+
end
|
480
470
|
end
|
481
471
|
end
|
482
472
|
|
@@ -511,8 +501,8 @@ module Sass::Script::Value
|
|
511
501
|
},
|
512
502
|
{
|
513
503
|
'dpi' => Rational(1),
|
514
|
-
'dpcm' => Rational(
|
515
|
-
'dppx' => Rational(96)
|
504
|
+
'dpcm' => Rational(1, 2.54),
|
505
|
+
'dppx' => Rational(1, 96)
|
516
506
|
}
|
517
507
|
]
|
518
508
|
|
@@ -2,8 +2,6 @@
|
|
2
2
|
module Sass::Script::Value
|
3
3
|
# A SassScript object representing a CSS string *or* a CSS identifier.
|
4
4
|
class String < Base
|
5
|
-
@@interpolation_deprecation = Sass::Deprecation.new
|
6
|
-
|
7
5
|
# The Ruby value of the string.
|
8
6
|
#
|
9
7
|
# @return [String]
|
@@ -78,13 +76,9 @@ module Sass::Script::Value
|
|
78
76
|
#
|
79
77
|
# @param value [String] See \{#value}
|
80
78
|
# @param type [Symbol] See \{#type}
|
81
|
-
|
82
|
-
# If this was created via a potentially-deprecated string interpolation,
|
83
|
-
# this is the replacement expression that should be suggested to the user.
|
84
|
-
def initialize(value, type = :identifier, deprecated_interp_equivalent = nil)
|
79
|
+
def initialize(value, type = :identifier)
|
85
80
|
super(value)
|
86
81
|
@type = type
|
87
|
-
@deprecated_interp_equivalent = deprecated_interp_equivalent
|
88
82
|
end
|
89
83
|
|
90
84
|
# @see Value#plus
|
@@ -108,29 +102,6 @@ module Sass::Script::Value
|
|
108
102
|
to_s(opts.merge(:sass => true))
|
109
103
|
end
|
110
104
|
|
111
|
-
def separator
|
112
|
-
check_deprecated_interp
|
113
|
-
super
|
114
|
-
end
|
115
|
-
|
116
|
-
def to_a
|
117
|
-
check_deprecated_interp
|
118
|
-
super
|
119
|
-
end
|
120
|
-
|
121
|
-
# Prints a warning if this string was created using potentially-deprecated
|
122
|
-
# interpolation.
|
123
|
-
def check_deprecated_interp
|
124
|
-
return unless @deprecated_interp_equivalent
|
125
|
-
|
126
|
-
@@interpolation_deprecation.warn(source_range.file, source_range.start_pos.line, <<WARNING)
|
127
|
-
\#{} interpolation near operators will be simplified in a future version of Sass.
|
128
|
-
To preserve the current behavior, use quotes:
|
129
|
-
|
130
|
-
#{@deprecated_interp_equivalent}
|
131
|
-
WARNING
|
132
|
-
end
|
133
|
-
|
134
105
|
def inspect
|
135
106
|
String.quote(value)
|
136
107
|
end
|
data/lib/sass/scss.rb
CHANGED
data/lib/sass/scss/css_parser.rb
CHANGED
@@ -47,15 +47,11 @@ module Sass
|
|
47
47
|
def keyframes_ruleset
|
48
48
|
start_pos = source_position
|
49
49
|
return unless (selector = keyframes_selector)
|
50
|
-
block(
|
51
|
-
node(
|
52
|
-
Sass::Tree::KeyframeRuleNode.new(
|
53
|
-
Sass::Util.strip_except_escapes(selector)),
|
54
|
-
start_pos),
|
55
|
-
:ruleset)
|
50
|
+
block(node(Sass::Tree::KeyframeRuleNode.new(selector.strip), start_pos), :ruleset)
|
56
51
|
end
|
57
52
|
|
58
|
-
@sass_script_parser = Sass::Script::CssParser
|
53
|
+
@sass_script_parser = Class.new(Sass::Script::CssParser)
|
54
|
+
@sass_script_parser.send(:include, ScriptParser)
|
59
55
|
end
|
60
56
|
end
|
61
57
|
end
|
data/lib/sass/scss/parser.rb
CHANGED
@@ -16,20 +16,21 @@ module Sass
|
|
16
16
|
# warnings and source maps.
|
17
17
|
# @param importer [Sass::Importers::Base] The importer used to import the
|
18
18
|
# file being parsed. Used for source maps.
|
19
|
-
# @param line [
|
19
|
+
# @param line [Fixnum] The 1-based line on which the source string appeared,
|
20
20
|
# if it's part of another document.
|
21
|
-
# @param offset [
|
21
|
+
# @param offset [Fixnum] The 1-based character (not byte) offset in the line on
|
22
22
|
# which the source string starts. Used for error reporting and sourcemap
|
23
23
|
# building.
|
24
|
+
# @comment
|
25
|
+
# rubocop:disable ParameterLists
|
24
26
|
def initialize(str, filename, importer, line = 1, offset = 1)
|
27
|
+
# rubocop:enable ParameterLists
|
25
28
|
@template = str
|
26
29
|
@filename = filename
|
27
30
|
@importer = importer
|
28
31
|
@line = line
|
29
32
|
@offset = offset
|
30
33
|
@strs = []
|
31
|
-
@expected = nil
|
32
|
-
@throw_error = false
|
33
34
|
end
|
34
35
|
|
35
36
|
# Parses an SCSS document.
|
@@ -99,18 +100,6 @@ module Sass
|
|
99
100
|
condition
|
100
101
|
end
|
101
102
|
|
102
|
-
# Parses a custom property value.
|
103
|
-
#
|
104
|
-
# @return [Array<String, Sass::Script;:Tree::Node>] The interpolated value.
|
105
|
-
# @raise [Sass::SyntaxError] if there's a syntax error in the value,
|
106
|
-
# or if it doesn't take up the entire input string.
|
107
|
-
def parse_declaration_value
|
108
|
-
init_scanner!
|
109
|
-
value = declaration_value
|
110
|
-
expected('"}"') unless value && @scanner.eos?
|
111
|
-
value
|
112
|
-
end
|
113
|
-
|
114
103
|
private
|
115
104
|
|
116
105
|
include Sass::SCSS::RX
|
@@ -128,7 +117,7 @@ module Sass
|
|
128
117
|
if @template.is_a?(StringScanner)
|
129
118
|
@template
|
130
119
|
else
|
131
|
-
Sass::Util::MultibyteStringScanner.new(@template.
|
120
|
+
Sass::Util::MultibyteStringScanner.new(@template.gsub("\r", ""))
|
132
121
|
end
|
133
122
|
end
|
134
123
|
|
@@ -203,7 +192,7 @@ module Sass
|
|
203
192
|
def directive
|
204
193
|
start_pos = source_position
|
205
194
|
return unless tok(/@/)
|
206
|
-
name =
|
195
|
+
name = tok!(IDENT)
|
207
196
|
ss
|
208
197
|
|
209
198
|
if (dir = special_directive(name, start_pos))
|
@@ -240,14 +229,14 @@ module Sass
|
|
240
229
|
end
|
241
230
|
|
242
231
|
def mixin_directive(start_pos)
|
243
|
-
name =
|
232
|
+
name = tok! IDENT
|
244
233
|
args, splat = sass_script(:parse_mixin_definition_arglist)
|
245
234
|
ss
|
246
235
|
block(node(Sass::Tree::MixinDefNode.new(name, args, splat), start_pos), :directive)
|
247
236
|
end
|
248
237
|
|
249
238
|
def include_directive(start_pos)
|
250
|
-
name =
|
239
|
+
name = tok! IDENT
|
251
240
|
args, keywords, splat, kwarg_splat = sass_script(:parse_mixin_include_arglist)
|
252
241
|
ss
|
253
242
|
include_node = node(
|
@@ -266,7 +255,7 @@ module Sass
|
|
266
255
|
end
|
267
256
|
|
268
257
|
def function_directive(start_pos)
|
269
|
-
name =
|
258
|
+
name = tok! IDENT
|
270
259
|
args, splat = sass_script(:parse_function_definition_arglist)
|
271
260
|
ss
|
272
261
|
block(node(Sass::Tree::FunctionNode.new(name, args, splat), start_pos), :function)
|
@@ -286,7 +275,7 @@ module Sass
|
|
286
275
|
|
287
276
|
def for_directive(start_pos)
|
288
277
|
tok!(/\$/)
|
289
|
-
var =
|
278
|
+
var = tok! IDENT
|
290
279
|
ss
|
291
280
|
|
292
281
|
tok!(/from/)
|
@@ -303,12 +292,12 @@ module Sass
|
|
303
292
|
|
304
293
|
def each_directive(start_pos)
|
305
294
|
tok!(/\$/)
|
306
|
-
vars = [
|
295
|
+
vars = [tok!(IDENT)]
|
307
296
|
ss
|
308
297
|
while tok(/,/)
|
309
298
|
ss
|
310
299
|
tok!(/\$/)
|
311
|
-
vars <<
|
300
|
+
vars << tok!(IDENT)
|
312
301
|
ss
|
313
302
|
end
|
314
303
|
|
@@ -407,8 +396,7 @@ module Sass
|
|
407
396
|
ss
|
408
397
|
media = media_query_list
|
409
398
|
if str =~ %r{^(https?:)?//} || media || supports || use_css_import?
|
410
|
-
return node(
|
411
|
-
Sass::Tree::CssImportNode.new(
|
399
|
+
return node(Sass::Tree::CssImportNode.new(
|
412
400
|
Sass::Script::Value::String.quote(str), media.to_a, supports), start_pos)
|
413
401
|
end
|
414
402
|
|
@@ -477,23 +465,12 @@ module Sass
|
|
477
465
|
return unless tok(/\(/)
|
478
466
|
res = ['(']
|
479
467
|
ss
|
480
|
-
|
481
|
-
res << sass_script(:parse_until, stop_at)
|
468
|
+
res << sass_script(:parse)
|
482
469
|
|
483
470
|
if tok(/:/)
|
484
471
|
res << ': '
|
485
472
|
ss
|
486
473
|
res << sass_script(:parse)
|
487
|
-
elsif comparison1 = tok(/=|[<>]=?/)
|
488
|
-
res << ' ' << comparison1 << ' '
|
489
|
-
ss
|
490
|
-
res << sass_script(:parse_until, stop_at)
|
491
|
-
if ((comparison1 == ">" || comparison1 == ">=") && comparison2 = tok(/>=?/)) ||
|
492
|
-
((comparison1 == "<" || comparison1 == "<=") && comparison2 = tok(/<=?/))
|
493
|
-
res << ' ' << comparison2 << ' '
|
494
|
-
ss
|
495
|
-
res << sass_script(:parse_until, stop_at)
|
496
|
-
end
|
497
474
|
end
|
498
475
|
res << tok!(/\)/)
|
499
476
|
ss
|
@@ -534,7 +511,7 @@ module Sass
|
|
534
511
|
|
535
512
|
def moz_document_function
|
536
513
|
val = interp_uri || _interp_string(:url_prefix) ||
|
537
|
-
_interp_string(:domain) || function(
|
514
|
+
_interp_string(:domain) || function(!:allow_var) || interpolation
|
538
515
|
return unless val
|
539
516
|
ss
|
540
517
|
val
|
@@ -553,10 +530,10 @@ module Sass
|
|
553
530
|
end
|
554
531
|
|
555
532
|
def at_root_directive_list
|
556
|
-
return unless (first =
|
533
|
+
return unless (first = tok(IDENT))
|
557
534
|
arr = [first]
|
558
535
|
ss
|
559
|
-
while (e =
|
536
|
+
while (e = tok(IDENT))
|
560
537
|
arr << e
|
561
538
|
ss
|
562
539
|
end
|
@@ -583,7 +560,7 @@ module Sass
|
|
583
560
|
def supports_clause
|
584
561
|
return unless tok(/supports\(/i)
|
585
562
|
ss
|
586
|
-
supports =
|
563
|
+
supports = supports_condition
|
587
564
|
ss
|
588
565
|
tok!(/\)/)
|
589
566
|
supports
|
@@ -593,10 +570,6 @@ module Sass
|
|
593
570
|
supports_negation || supports_operator || supports_interpolation
|
594
571
|
end
|
595
572
|
|
596
|
-
def import_supports_condition
|
597
|
-
supports_condition || supports_declaration
|
598
|
-
end
|
599
|
-
|
600
573
|
def supports_negation
|
601
574
|
return unless tok(/not/i)
|
602
575
|
ss
|
@@ -616,13 +589,6 @@ module Sass
|
|
616
589
|
cond
|
617
590
|
end
|
618
591
|
|
619
|
-
def supports_declaration
|
620
|
-
name = sass_script(:parse)
|
621
|
-
tok!(/:/); ss
|
622
|
-
value = sass_script(:parse)
|
623
|
-
Sass::Supports::Declaration.new(name, value)
|
624
|
-
end
|
625
|
-
|
626
592
|
def supports_condition_in_parens
|
627
593
|
interp = supports_interpolation
|
628
594
|
return interp if interp
|
@@ -631,9 +597,11 @@ module Sass
|
|
631
597
|
tok!(/\)/); ss
|
632
598
|
cond
|
633
599
|
else
|
634
|
-
|
600
|
+
name = sass_script(:parse)
|
601
|
+
tok!(/:/); ss
|
602
|
+
value = sass_script(:parse)
|
635
603
|
tok!(/\)/); ss
|
636
|
-
|
604
|
+
Sass::Supports::Declaration.new(name, value)
|
637
605
|
end
|
638
606
|
end
|
639
607
|
|
@@ -647,12 +615,12 @@ module Sass
|
|
647
615
|
def variable
|
648
616
|
return unless tok(/\$/)
|
649
617
|
start_pos = source_position
|
650
|
-
name =
|
618
|
+
name = tok!(IDENT)
|
651
619
|
ss; tok!(/:/); ss
|
652
620
|
|
653
621
|
expr = sass_script(:parse)
|
654
622
|
while tok(/!/)
|
655
|
-
flag_name =
|
623
|
+
flag_name = tok!(IDENT)
|
656
624
|
if flag_name == 'default'
|
657
625
|
guarded ||= true
|
658
626
|
elsif flag_name == 'global'
|
@@ -672,15 +640,14 @@ module Sass
|
|
672
640
|
# are disallowed by the CSS spec,
|
673
641
|
# but they're included here for compatibility
|
674
642
|
# with some proprietary MS properties
|
675
|
-
str {ss if tok(
|
643
|
+
str {ss if tok(/[\/,:.=]/)}
|
676
644
|
end
|
677
645
|
|
678
646
|
def ruleset
|
679
647
|
start_pos = source_position
|
680
648
|
return unless (rules = almost_any_value)
|
681
|
-
block(
|
682
|
-
|
683
|
-
Sass::Tree::RuleNode.new(rules, range(start_pos)), start_pos), :ruleset)
|
649
|
+
block(node(
|
650
|
+
Sass::Tree::RuleNode.new(rules, range(start_pos)), start_pos), :ruleset)
|
684
651
|
end
|
685
652
|
|
686
653
|
def block(node, context)
|
@@ -755,9 +722,8 @@ module Sass
|
|
755
722
|
selector << additional_selector
|
756
723
|
end
|
757
724
|
|
758
|
-
block(
|
759
|
-
|
760
|
-
Sass::Tree::RuleNode.new(merge(selector), range(start_pos)), start_pos), :ruleset)
|
725
|
+
block(node(
|
726
|
+
Sass::Tree::RuleNode.new(merge(selector), range(start_pos)), start_pos), :ruleset)
|
761
727
|
end
|
762
728
|
|
763
729
|
# Tries to parse a declaration, and returns the value parsed so far if it
|
@@ -790,12 +756,6 @@ module Sass
|
|
790
756
|
mid = [str {ss}]
|
791
757
|
return name + mid unless tok(/:/)
|
792
758
|
mid << ':'
|
793
|
-
|
794
|
-
# If this is a CSS variable, parse it as a property no matter what.
|
795
|
-
if name.first.is_a?(String) && name.first.start_with?("--")
|
796
|
-
return css_variable_declaration(name, name_start_pos, name_end_pos)
|
797
|
-
end
|
798
|
-
|
799
759
|
return name + mid + [':'] if tok(/:/)
|
800
760
|
mid << str {ss}
|
801
761
|
post_colon_whitespace = !mid.last.empty?
|
@@ -831,7 +791,7 @@ module Sass
|
|
831
791
|
ss
|
832
792
|
require_block = tok?(/\{/)
|
833
793
|
|
834
|
-
node = node(Sass::Tree::PropNode.new(name.flatten.compact,
|
794
|
+
node = node(Sass::Tree::PropNode.new(name.flatten.compact, value, :new),
|
835
795
|
name_start_pos, value_end_pos)
|
836
796
|
node.name_source_range = range(name_start_pos, name_end_pos)
|
837
797
|
node.value_source_range = range(value_start_pos, value_end_pos)
|
@@ -840,21 +800,13 @@ module Sass
|
|
840
800
|
nested_properties! node
|
841
801
|
end
|
842
802
|
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
node.name_source_range = range(name_start_pos, name_end_pos)
|
851
|
-
node.value_source_range = range(value_start_pos, value_end_pos)
|
852
|
-
node
|
853
|
-
end
|
854
|
-
|
855
|
-
# This production consumes values that could be a selector, an expression,
|
856
|
-
# or a combination of both. It respects strings and comments and supports
|
857
|
-
# interpolation. It will consume up to "{", "}", ";", or "!".
|
803
|
+
# This production is similar to the CSS [`<any-value>`][any-value]
|
804
|
+
# production, but as the name implies, not quite the same. It's meant to
|
805
|
+
# consume values that could be a selector, an expression, or a combination
|
806
|
+
# of both. It respects strings and comments and supports interpolation. It
|
807
|
+
# will consume up to "{", "}", ";", or "!".
|
808
|
+
#
|
809
|
+
# [any-value]: http://dev.w3.org/csswg/css-variables/#typedef-any-value
|
858
810
|
#
|
859
811
|
# Values consumed by this production will usually be parsed more
|
860
812
|
# thoroughly once interpolation has been resolved.
|
@@ -874,9 +826,6 @@ module Sass
|
|
874
826
|
|
|
875
827
|
(?!url\()
|
876
828
|
[^"'/\#!;\{\}] # "
|
877
|
-
|
|
878
|
-
# interp_uri will handle most url() calls, but not ones that take strings
|
879
|
-
url\(#{W}(?=")
|
880
829
|
|
|
881
830
|
/(?![/*])
|
882
831
|
|
|
@@ -888,60 +837,6 @@ module Sass
|
|
888
837
|
interpolation(:warn_for_color)
|
889
838
|
end
|
890
839
|
|
891
|
-
def declaration_value(top_level: true)
|
892
|
-
return unless (tok = declaration_value_token(top_level))
|
893
|
-
value = [tok]
|
894
|
-
while (tok = declaration_value_token(top_level))
|
895
|
-
value << tok
|
896
|
-
end
|
897
|
-
merge(value)
|
898
|
-
end
|
899
|
-
|
900
|
-
def declaration_value_token(top_level)
|
901
|
-
# This comes, more or less, from the [token consumption algorithm][].
|
902
|
-
# However, since we don't have to worry about the token semantics, we
|
903
|
-
# just consume everything until we come across a token with special
|
904
|
-
# semantics.
|
905
|
-
#
|
906
|
-
# [token consumption algorithm]: https://drafts.csswg.org/css-syntax-3/#consume-token.
|
907
|
-
result = tok(%r{
|
908
|
-
(
|
909
|
-
(?!
|
910
|
-
url\(
|
911
|
-
)
|
912
|
-
[^()\[\]{}"'#/ \t\r\n\f#{top_level ? ";" : ""}]
|
913
|
-
|
|
914
|
-
\#(?!\{)
|
915
|
-
|
|
916
|
-
/(?!\*)
|
917
|
-
)+
|
918
|
-
}xi) || interp_string || interp_uri || interpolation || tok(COMMENT)
|
919
|
-
return result if result
|
920
|
-
|
921
|
-
# Fold together multiple characters of whitespace that don't include
|
922
|
-
# newlines. The value only cares about the tokenization, so this is safe
|
923
|
-
# as long as we don't delete whitespace entirely. It's important that we
|
924
|
-
# fold here rather than post-processing, since we aren't allowed to fold
|
925
|
-
# whitespace within strings and we lose that context later on.
|
926
|
-
if (ws = tok(S))
|
927
|
-
return ws.include?("\n") ? ws.gsub(/\A[^\n]*/, '') : ' '
|
928
|
-
end
|
929
|
-
|
930
|
-
if tok(/\(/)
|
931
|
-
value = declaration_value(top_level: false)
|
932
|
-
tok!(/\)/)
|
933
|
-
['(', *value, ')']
|
934
|
-
elsif tok(/\[/)
|
935
|
-
value = declaration_value(top_level: false)
|
936
|
-
tok!(/\]/)
|
937
|
-
['[', *value, ']']
|
938
|
-
elsif tok(/\{/)
|
939
|
-
value = declaration_value(top_level: false)
|
940
|
-
tok!(/\}/)
|
941
|
-
['{', *value, '}']
|
942
|
-
end
|
943
|
-
end
|
944
|
-
|
945
840
|
def declaration
|
946
841
|
# This allows the "*prop: val", ":prop: val", "#prop: val", and ".prop:
|
947
842
|
# val" hacks.
|
@@ -967,7 +862,7 @@ module Sass
|
|
967
862
|
ss
|
968
863
|
require_block = tok?(/\{/)
|
969
864
|
|
970
|
-
node = node(Sass::Tree::PropNode.new(name.flatten.compact,
|
865
|
+
node = node(Sass::Tree::PropNode.new(name.flatten.compact, value, :new),
|
971
866
|
name_start_pos, value_end_pos)
|
972
867
|
node.name_source_range = range(name_start_pos, name_end_pos)
|
973
868
|
node.value_source_range = range(value_start_pos, value_end_pos)
|
@@ -990,11 +885,8 @@ module Sass
|
|
990
885
|
# we don't parse it at all, and instead return a plain old string
|
991
886
|
# containing the value.
|
992
887
|
# This results in a dramatic speed increase.
|
993
|
-
if (val = tok(STATIC_VALUE))
|
994
|
-
|
995
|
-
str = Sass::Script::Tree::Literal.new(
|
996
|
-
Sass::Script::Value::String.new(
|
997
|
-
Sass::Util.strip_except_escapes(val)))
|
888
|
+
if (val = tok(STATIC_VALUE, true))
|
889
|
+
str = Sass::Script::Tree::Literal.new(Sass::Script::Value::String.new(val.strip))
|
998
890
|
str.line = start_pos.line
|
999
891
|
str.source_range = range(start_pos)
|
1000
892
|
return str
|
@@ -1051,7 +943,7 @@ module Sass
|
|
1051
943
|
def var_expr
|
1052
944
|
return unless tok(/\$/)
|
1053
945
|
line = @line
|
1054
|
-
var = Sass::Script::Tree::Variable.new(
|
946
|
+
var = Sass::Script::Tree::Variable.new(tok!(IDENT))
|
1055
947
|
var.line = line
|
1056
948
|
var
|
1057
949
|
end
|
@@ -1089,27 +981,11 @@ module Sass
|
|
1089
981
|
res
|
1090
982
|
end
|
1091
983
|
|
1092
|
-
def
|
1093
|
-
|
1094
|
-
end
|
1095
|
-
|
1096
|
-
def ident!
|
1097
|
-
Sass::Util.normalize_ident_escapes(tok!(IDENT))
|
1098
|
-
end
|
1099
|
-
|
1100
|
-
def name
|
1101
|
-
(name = tok(NAME)) && Sass::Util.normalize_ident_escapes(name)
|
1102
|
-
end
|
1103
|
-
|
1104
|
-
def name!
|
1105
|
-
Sass::Util.normalize_ident_escapes(tok!(NAME))
|
1106
|
-
end
|
1107
|
-
|
1108
|
-
def interp_ident
|
1109
|
-
val = ident || interpolation(:warn_for_color) || tok(IDENT_HYPHEN_INTERP)
|
984
|
+
def interp_ident(start = IDENT)
|
985
|
+
val = tok(start) || interpolation(:warn_for_color) || tok(IDENT_HYPHEN_INTERP, true)
|
1110
986
|
return unless val
|
1111
987
|
res = [val]
|
1112
|
-
while (val =
|
988
|
+
while (val = tok(NAME) || interpolation(:warn_for_color))
|
1113
989
|
res << val
|
1114
990
|
end
|
1115
991
|
res
|
@@ -1123,7 +999,7 @@ module Sass
|
|
1123
999
|
end
|
1124
1000
|
|
1125
1001
|
def str
|
1126
|
-
@strs.push
|
1002
|
+
@strs.push ""
|
1127
1003
|
yield
|
1128
1004
|
@strs.last
|
1129
1005
|
ensure
|
@@ -1151,7 +1027,8 @@ module Sass
|
|
1151
1027
|
node
|
1152
1028
|
end
|
1153
1029
|
|
1154
|
-
@sass_script_parser = Sass::Script::Parser
|
1030
|
+
@sass_script_parser = Class.new(Sass::Script::Parser)
|
1031
|
+
@sass_script_parser.send(:include, ScriptParser)
|
1155
1032
|
|
1156
1033
|
class << self
|
1157
1034
|
# @private
|
@@ -1160,7 +1037,7 @@ module Sass
|
|
1160
1037
|
|
1161
1038
|
def sass_script(*args)
|
1162
1039
|
parser = self.class.sass_script_parser.new(@scanner, @line, @offset,
|
1163
|
-
|
1040
|
+
:filename => @filename, :importer => @importer)
|
1164
1041
|
result = parser.send(*args)
|
1165
1042
|
unless @strs.empty?
|
1166
1043
|
# Convert to CSS manually so that comments are ignored.
|
@@ -1185,7 +1062,7 @@ module Sass
|
|
1185
1062
|
:media_expr => "media expression (e.g. (min-device-width: 800px))",
|
1186
1063
|
:at_root_query => "@at-root query (e.g. (without: media))",
|
1187
1064
|
:at_root_directive_list => '* or identifier',
|
1188
|
-
:
|
1065
|
+
:pseudo_args => "expression (e.g. fr, 2n+1)",
|
1189
1066
|
:interp_ident => "identifier",
|
1190
1067
|
:qualified_name => "identifier",
|
1191
1068
|
:expr => "expression (e.g. 1px, bold)",
|
@@ -1200,9 +1077,9 @@ module Sass
|
|
1200
1077
|
:keyframes_selector => "keyframes selector (e.g. 10%)"
|
1201
1078
|
}
|
1202
1079
|
|
1203
|
-
TOK_NAMES =
|
1080
|
+
TOK_NAMES = Sass::Util.to_hash(Sass::SCSS::RX.constants.map do |c|
|
1204
1081
|
[Sass::SCSS::RX.const_get(c), c.downcase]
|
1205
|
-
end
|
1082
|
+
end).merge(
|
1206
1083
|
IDENT => "identifier",
|
1207
1084
|
/[;{}]/ => '";"',
|
1208
1085
|
/\b(without|with)\b/ => '"with" or "without"'
|
@@ -1225,7 +1102,7 @@ module Sass
|
|
1225
1102
|
|
1226
1103
|
unless name
|
1227
1104
|
# Display basic regexps as plain old strings
|
1228
|
-
source = rx.source.gsub(
|
1105
|
+
source = rx.source.gsub(/\\\//, '/')
|
1229
1106
|
string = rx.source.gsub(/\\(.)/, '\1')
|
1230
1107
|
name = source == Regexp.escape(string) ? string.inspect : rx.inspect
|
1231
1108
|
end
|
@@ -1256,20 +1133,14 @@ module Sass
|
|
1256
1133
|
line = @line
|
1257
1134
|
offset = @offset
|
1258
1135
|
expected = @expected
|
1259
|
-
|
1260
|
-
logger = Sass::Logger::Delayed.install!
|
1261
1136
|
if catch(:_sass_parser_error) {yield; false}
|
1262
1137
|
@scanner.pos = pos
|
1263
1138
|
@line = line
|
1264
1139
|
@offset = offset
|
1265
1140
|
@expected = expected
|
1266
1141
|
{:pos => pos, :line => line, :expected => @expected, :block => block}
|
1267
|
-
else
|
1268
|
-
logger.flush
|
1269
|
-
nil
|
1270
1142
|
end
|
1271
1143
|
ensure
|
1272
|
-
logger.uninstall! if logger
|
1273
1144
|
@throw_error = old_throw_error
|
1274
1145
|
end
|
1275
1146
|
|
@@ -1314,24 +1185,35 @@ module Sass
|
|
1314
1185
|
# This is important because `#tok` is called all the time.
|
1315
1186
|
NEWLINE = "\n"
|
1316
1187
|
|
1317
|
-
def tok(rx)
|
1188
|
+
def tok(rx, last_group_lookahead = false)
|
1318
1189
|
res = @scanner.scan(rx)
|
1190
|
+
if res
|
1191
|
+
# This fixes https://github.com/nex3/sass/issues/104, which affects
|
1192
|
+
# Ruby 1.8.7 and REE. This fix is to replace the ?= zero-width
|
1193
|
+
# positive lookahead operator in the Regexp (which matches without
|
1194
|
+
# consuming the matched group), with a match that does consume the
|
1195
|
+
# group, but then rewinds the scanner and removes the group from the
|
1196
|
+
# end of the matched string. This fix makes the assumption that the
|
1197
|
+
# matched group will always occur at the end of the match.
|
1198
|
+
if last_group_lookahead && @scanner[-1]
|
1199
|
+
@scanner.pos -= @scanner[-1].length
|
1200
|
+
res.slice!(-@scanner[-1].length..-1)
|
1201
|
+
end
|
1319
1202
|
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
@offset += res.size
|
1328
|
-
end
|
1203
|
+
newline_count = res.count(NEWLINE)
|
1204
|
+
if newline_count > 0
|
1205
|
+
@line += newline_count
|
1206
|
+
@offset = res[res.rindex(NEWLINE)..-1].size
|
1207
|
+
else
|
1208
|
+
@offset += res.size
|
1209
|
+
end
|
1329
1210
|
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1211
|
+
@expected = nil
|
1212
|
+
if !@strs.empty? && rx != COMMENT && rx != SINGLE_LINE_COMMENT
|
1213
|
+
@strs.each {|s| s << res}
|
1214
|
+
end
|
1215
|
+
res
|
1333
1216
|
end
|
1334
|
-
res
|
1335
1217
|
end
|
1336
1218
|
|
1337
1219
|
# Remove a vendor prefix from `str`.
|