oreorenasass 3.4.4 → 3.4.5
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 +50 -70
- data/Rakefile +5 -26
- data/VERSION +1 -1
- data/VERSION_NAME +1 -1
- data/bin/sass +1 -1
- data/bin/scss +1 -1
- data/lib/sass.rb +12 -19
- data/lib/sass/cache_stores/base.rb +2 -2
- data/lib/sass/cache_stores/chain.rb +1 -2
- data/lib/sass/cache_stores/filesystem.rb +5 -1
- data/lib/sass/cache_stores/memory.rb +1 -1
- data/lib/sass/cache_stores/null.rb +2 -2
- data/lib/sass/callbacks.rb +0 -1
- data/lib/sass/css.rb +13 -11
- data/lib/sass/engine.rb +173 -424
- data/lib/sass/environment.rb +58 -148
- data/lib/sass/error.rb +14 -11
- data/lib/sass/exec.rb +703 -5
- data/lib/sass/importers/base.rb +6 -49
- data/lib/sass/importers/filesystem.rb +19 -44
- data/lib/sass/logger.rb +4 -1
- data/lib/sass/logger/base.rb +4 -2
- data/lib/sass/logger/log_level.rb +7 -3
- data/lib/sass/media.rb +23 -20
- data/lib/sass/plugin.rb +7 -7
- data/lib/sass/plugin/compiler.rb +145 -304
- data/lib/sass/plugin/configuration.rb +23 -18
- data/lib/sass/plugin/merb.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +3 -3
- data/lib/sass/repl.rb +3 -3
- data/lib/sass/script.rb +8 -35
- data/lib/sass/script/{value/arg_list.rb → arg_list.rb} +25 -9
- data/lib/sass/script/bool.rb +18 -0
- data/lib/sass/script/color.rb +606 -0
- data/lib/sass/script/css_lexer.rb +4 -8
- data/lib/sass/script/css_parser.rb +2 -5
- data/lib/sass/script/funcall.rb +245 -0
- data/lib/sass/script/functions.rb +408 -1491
- data/lib/sass/script/interpolation.rb +79 -0
- data/lib/sass/script/lexer.rb +68 -172
- data/lib/sass/script/list.rb +85 -0
- data/lib/sass/script/literal.rb +221 -0
- data/lib/sass/script/{tree/node.rb → node.rb} +12 -22
- data/lib/sass/script/{value/null.rb → null.rb} +7 -14
- data/lib/sass/script/{value/number.rb → number.rb} +75 -152
- data/lib/sass/script/{tree/operation.rb → operation.rb} +24 -17
- data/lib/sass/script/parser.rb +110 -245
- data/lib/sass/script/string.rb +51 -0
- data/lib/sass/script/{tree/string_interpolation.rb → string_interpolation.rb} +4 -5
- data/lib/sass/script/{tree/unary_operation.rb → unary_operation.rb} +6 -6
- data/lib/sass/script/variable.rb +58 -0
- data/lib/sass/scss/css_parser.rb +3 -9
- data/lib/sass/scss/parser.rb +421 -450
- data/lib/sass/scss/rx.rb +11 -19
- data/lib/sass/scss/static_parser.rb +7 -321
- data/lib/sass/selector.rb +194 -68
- data/lib/sass/selector/abstract_sequence.rb +14 -29
- data/lib/sass/selector/comma_sequence.rb +25 -108
- data/lib/sass/selector/sequence.rb +66 -159
- data/lib/sass/selector/simple.rb +25 -23
- data/lib/sass/selector/simple_sequence.rb +63 -173
- data/lib/sass/shared.rb +1 -1
- data/lib/sass/supports.rb +15 -13
- data/lib/sass/tree/charset_node.rb +1 -1
- data/lib/sass/tree/comment_node.rb +3 -3
- data/lib/sass/tree/css_import_node.rb +11 -11
- data/lib/sass/tree/debug_node.rb +2 -2
- data/lib/sass/tree/directive_node.rb +4 -21
- data/lib/sass/tree/each_node.rb +8 -8
- data/lib/sass/tree/extend_node.rb +7 -14
- data/lib/sass/tree/for_node.rb +4 -4
- data/lib/sass/tree/function_node.rb +4 -9
- data/lib/sass/tree/if_node.rb +1 -1
- data/lib/sass/tree/import_node.rb +5 -4
- data/lib/sass/tree/media_node.rb +14 -4
- data/lib/sass/tree/mixin_def_node.rb +4 -4
- data/lib/sass/tree/mixin_node.rb +8 -21
- data/lib/sass/tree/node.rb +12 -54
- data/lib/sass/tree/prop_node.rb +20 -39
- data/lib/sass/tree/return_node.rb +2 -3
- data/lib/sass/tree/root_node.rb +3 -19
- data/lib/sass/tree/rule_node.rb +22 -35
- data/lib/sass/tree/supports_node.rb +13 -0
- data/lib/sass/tree/trace_node.rb +1 -2
- data/lib/sass/tree/variable_node.rb +3 -9
- data/lib/sass/tree/visitors/base.rb +8 -5
- data/lib/sass/tree/visitors/check_nesting.rb +19 -49
- data/lib/sass/tree/visitors/convert.rb +56 -74
- data/lib/sass/tree/visitors/cssize.rb +74 -202
- data/lib/sass/tree/visitors/deep_copy.rb +5 -10
- data/lib/sass/tree/visitors/extend.rb +7 -7
- data/lib/sass/tree/visitors/perform.rb +185 -278
- data/lib/sass/tree/visitors/set_options.rb +6 -20
- data/lib/sass/tree/visitors/to_css.rb +81 -234
- data/lib/sass/tree/warn_node.rb +2 -2
- data/lib/sass/tree/while_node.rb +2 -2
- data/lib/sass/util.rb +152 -522
- data/lib/sass/util/multibyte_string_scanner.rb +0 -2
- data/lib/sass/util/subset_map.rb +3 -4
- data/lib/sass/util/test.rb +1 -0
- data/lib/sass/version.rb +22 -20
- data/test/Gemfile +3 -0
- data/test/Gemfile.lock +10 -0
- data/test/sass/cache_test.rb +20 -62
- data/test/sass/callbacks_test.rb +1 -1
- data/test/sass/conversion_test.rb +2 -296
- data/test/sass/css2sass_test.rb +4 -23
- data/test/sass/engine_test.rb +354 -411
- data/test/sass/exec_test.rb +2 -2
- data/test/sass/extend_test.rb +145 -324
- data/test/sass/functions_test.rb +86 -873
- data/test/sass/importer_test.rb +21 -241
- data/test/sass/logger_test.rb +1 -1
- data/test/sass/more_results/more_import.css +1 -1
- data/test/sass/plugin_test.rb +26 -16
- 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 +7 -36
- data/test/sass/script_test.rb +53 -485
- data/test/sass/scss/css_test.rb +28 -143
- data/test/sass/scss/rx_test.rb +4 -4
- data/test/sass/scss/scss_test.rb +325 -2119
- data/test/sass/templates/scss_import.scss +1 -2
- data/test/sass/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
- data/test/sass/util/subset_map_test.rb +2 -2
- data/test/sass/util_test.rb +1 -86
- data/test/test_helper.rb +8 -37
- metadata +19 -66
- data/lib/sass/exec/base.rb +0 -187
- data/lib/sass/exec/sass_convert.rb +0 -264
- data/lib/sass/exec/sass_scss.rb +0 -424
- data/lib/sass/features.rb +0 -47
- data/lib/sass/script/tree.rb +0 -16
- data/lib/sass/script/tree/funcall.rb +0 -306
- data/lib/sass/script/tree/interpolation.rb +0 -118
- data/lib/sass/script/tree/list_literal.rb +0 -77
- data/lib/sass/script/tree/literal.rb +0 -45
- data/lib/sass/script/tree/map_literal.rb +0 -64
- data/lib/sass/script/tree/selector.rb +0 -26
- data/lib/sass/script/tree/variable.rb +0 -57
- data/lib/sass/script/value.rb +0 -11
- data/lib/sass/script/value/base.rb +0 -240
- data/lib/sass/script/value/bool.rb +0 -35
- data/lib/sass/script/value/color.rb +0 -680
- data/lib/sass/script/value/helpers.rb +0 -262
- data/lib/sass/script/value/list.rb +0 -113
- data/lib/sass/script/value/map.rb +0 -70
- data/lib/sass/script/value/string.rb +0 -97
- data/lib/sass/selector/pseudo.rb +0 -256
- data/lib/sass/source/map.rb +0 -210
- data/lib/sass/source/position.rb +0 -39
- data/lib/sass/source/range.rb +0 -41
- data/lib/sass/stack.rb +0 -120
- data/lib/sass/tree/at_root_node.rb +0 -83
- data/lib/sass/tree/error_node.rb +0 -18
- data/lib/sass/tree/keyframe_rule_node.rb +0 -15
- data/lib/sass/util/cross_platform_random.rb +0 -19
- data/lib/sass/util/normalized_map.rb +0 -130
- data/lib/sass/util/ordered_hash.rb +0 -192
- data/test/sass/compiler_test.rb +0 -232
- data/test/sass/encoding_test.rb +0 -219
- data/test/sass/source_map_test.rb +0 -977
- data/test/sass/superselector_test.rb +0 -191
- data/test/sass/util/normalized_map_test.rb +0 -51
- data/test/sass/value_helpers_test.rb +0 -179
@@ -1,4 +1,13 @@
|
|
1
|
-
|
1
|
+
require 'set'
|
2
|
+
require 'sass/script/string'
|
3
|
+
require 'sass/script/number'
|
4
|
+
require 'sass/script/color'
|
5
|
+
require 'sass/script/functions'
|
6
|
+
require 'sass/script/unary_operation'
|
7
|
+
require 'sass/script/interpolation'
|
8
|
+
require 'sass/script/string_interpolation'
|
9
|
+
|
10
|
+
module Sass::Script
|
2
11
|
# A SassScript parse node representing a binary operation,
|
3
12
|
# such as `$a + $b` or `"foo" + 1`.
|
4
13
|
class Operation < Node
|
@@ -6,12 +15,12 @@ module Sass::Script::Tree
|
|
6
15
|
attr_reader :operand2
|
7
16
|
attr_reader :operator
|
8
17
|
|
9
|
-
# @param operand1 [
|
18
|
+
# @param operand1 [Script::Node] The parse-tree node
|
10
19
|
# for the right-hand side of the operator
|
11
|
-
# @param operand2 [
|
20
|
+
# @param operand2 [Script::Node] The parse-tree node
|
12
21
|
# for the left-hand side of the operator
|
13
22
|
# @param operator [Symbol] The operator to perform.
|
14
|
-
# This should be one of the binary operator names in {
|
23
|
+
# This should be one of the binary operator names in {Lexer::OPERATORS}
|
15
24
|
def initialize(operand1, operand2, operator)
|
16
25
|
@operand1 = operand1
|
17
26
|
@operand2 = operand2
|
@@ -32,7 +41,7 @@ module Sass::Script::Tree
|
|
32
41
|
case @operator
|
33
42
|
when :comma; ", "
|
34
43
|
when :space; " "
|
35
|
-
else; " #{
|
44
|
+
else; " #{Lexer::OPERATORS_REVERSE[@operator]} "
|
36
45
|
end
|
37
46
|
"#{o1}#{sep}#{o2}"
|
38
47
|
end
|
@@ -58,38 +67,36 @@ module Sass::Script::Tree
|
|
58
67
|
# Evaluates the operation.
|
59
68
|
#
|
60
69
|
# @param environment [Sass::Environment] The environment in which to evaluate the SassScript
|
61
|
-
# @return [
|
70
|
+
# @return [Literal] The SassScript object that is the value of the operation
|
62
71
|
# @raise [Sass::SyntaxError] if the operation is undefined for the operands
|
63
72
|
def _perform(environment)
|
64
|
-
|
73
|
+
literal1 = @operand1.perform(environment)
|
65
74
|
|
66
75
|
# Special-case :and and :or to support short-circuiting.
|
67
76
|
if @operator == :and
|
68
|
-
return
|
77
|
+
return literal1.to_bool ? @operand2.perform(environment) : literal1
|
69
78
|
elsif @operator == :or
|
70
|
-
return
|
79
|
+
return literal1.to_bool ? literal1 : @operand2.perform(environment)
|
71
80
|
end
|
72
81
|
|
73
|
-
|
82
|
+
literal2 = @operand2.perform(environment)
|
74
83
|
|
75
|
-
if (
|
76
|
-
|
77
|
-
raise Sass::SyntaxError.new(
|
78
|
-
"Invalid null operation: \"#{value1.inspect} #{@operator} #{value2.inspect}\".")
|
84
|
+
if (literal1.is_a?(Null) || literal2.is_a?(Null)) && @operator != :eq && @operator != :neq
|
85
|
+
raise Sass::SyntaxError.new("Invalid null operation: \"#{literal1.inspect} #{@operator} #{literal2.inspect}\".")
|
79
86
|
end
|
80
87
|
|
81
88
|
begin
|
82
|
-
opts(
|
89
|
+
opts(literal1.send(@operator, literal2))
|
83
90
|
rescue NoMethodError => e
|
84
91
|
raise e unless e.name.to_s == @operator.to_s
|
85
|
-
raise Sass::SyntaxError.new("Undefined operation: \"#{
|
92
|
+
raise Sass::SyntaxError.new("Undefined operation: \"#{literal1} #{@operator} #{literal2}\".")
|
86
93
|
end
|
87
94
|
end
|
88
95
|
|
89
96
|
private
|
90
97
|
|
91
98
|
def operand_to_sass(op, side, opts)
|
92
|
-
return "(#{op.to_sass(opts)})" if op.is_a?(
|
99
|
+
return "(#{op.to_sass(opts)})" if op.is_a?(List)
|
93
100
|
return op.to_sass(opts) unless op.is_a?(Operation)
|
94
101
|
|
95
102
|
pred = Sass::Script::Parser.precedence_of(@operator)
|
data/lib/sass/script/parser.rb
CHANGED
@@ -3,7 +3,7 @@ require 'sass/script/lexer'
|
|
3
3
|
module Sass
|
4
4
|
module Script
|
5
5
|
# The parser for SassScript.
|
6
|
-
# It parses a string of code into a tree of {Script::
|
6
|
+
# It parses a string of code into a tree of {Script::Node}s.
|
7
7
|
class Parser
|
8
8
|
# The line number of the parser's current position.
|
9
9
|
#
|
@@ -12,18 +12,11 @@ module Sass
|
|
12
12
|
@lexer.line
|
13
13
|
end
|
14
14
|
|
15
|
-
# The column number of the parser's current position.
|
16
|
-
#
|
17
|
-
# @return [Fixnum]
|
18
|
-
def offset
|
19
|
-
@lexer.offset
|
20
|
-
end
|
21
|
-
|
22
15
|
# @param str [String, StringScanner] The source text to parse
|
23
16
|
# @param line [Fixnum] The line on which the SassScript appears.
|
24
|
-
# Used for error reporting
|
25
|
-
# @param offset [Fixnum] The
|
26
|
-
# Used for error reporting
|
17
|
+
# Used for error reporting
|
18
|
+
# @param offset [Fixnum] The number of characters in on which the SassScript appears.
|
19
|
+
# Used for error reporting
|
27
20
|
# @param options [{Symbol => Object}] An options hash;
|
28
21
|
# see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
|
29
22
|
def initialize(str, line, offset, options = {})
|
@@ -36,19 +29,13 @@ module Sass
|
|
36
29
|
# which signals the end of an interpolated segment,
|
37
30
|
# it returns rather than throwing an error.
|
38
31
|
#
|
39
|
-
# @
|
40
|
-
# interoplation should cause a warning.
|
41
|
-
# @return [Script::Tree::Node] The root node of the parse tree
|
32
|
+
# @return [Script::Node] The root node of the parse tree
|
42
33
|
# @raise [Sass::SyntaxError] if the expression isn't valid SassScript
|
43
|
-
def parse_interpolated
|
44
|
-
# Start two characters back to compensate for #{
|
45
|
-
start_pos = Sass::Source::Position.new(line, offset - 2)
|
34
|
+
def parse_interpolated
|
46
35
|
expr = assert_expr :expr
|
47
36
|
assert_tok :end_interpolation
|
48
|
-
expr = Sass::Script::Tree::Interpolation.new(
|
49
|
-
nil, expr, nil, !:wb, !:wa, !:originally_text, warn_for_color)
|
50
37
|
expr.options = @options
|
51
|
-
|
38
|
+
expr
|
52
39
|
rescue Sass::SyntaxError => e
|
53
40
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
54
41
|
raise e
|
@@ -56,7 +43,7 @@ module Sass
|
|
56
43
|
|
57
44
|
# Parses a SassScript expression.
|
58
45
|
#
|
59
|
-
# @return [Script::
|
46
|
+
# @return [Script::Node] The root node of the parse tree
|
60
47
|
# @raise [Sass::SyntaxError] if the expression isn't valid SassScript
|
61
48
|
def parse
|
62
49
|
expr = assert_expr :expr
|
@@ -71,8 +58,8 @@ module Sass
|
|
71
58
|
# Parses a SassScript expression,
|
72
59
|
# ending it when it encounters one of the given identifier tokens.
|
73
60
|
#
|
74
|
-
# @param
|
75
|
-
# @return [Script::
|
61
|
+
# @param [#include?(String)] A set of strings that delimit the expression.
|
62
|
+
# @return [Script::Node] The root node of the parse tree
|
76
63
|
# @raise [Sass::SyntaxError] if the expression isn't valid SassScript
|
77
64
|
def parse_until(tokens)
|
78
65
|
@stop_at = tokens
|
@@ -87,17 +74,14 @@ module Sass
|
|
87
74
|
|
88
75
|
# Parses the argument list for a mixin include.
|
89
76
|
#
|
90
|
-
# @return [(Array<Script::
|
91
|
-
# {String => Script::Tree::Node},
|
92
|
-
# Script::Tree::Node,
|
93
|
-
# Script::Tree::Node)]
|
77
|
+
# @return [(Array<Script::Node>, {String => Script::Node}, Script::Node)]
|
94
78
|
# The root nodes of the positional arguments, keyword arguments, and
|
95
|
-
# splat argument
|
79
|
+
# splat argument. Keyword arguments are in a hash from names to values.
|
96
80
|
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
|
97
81
|
def parse_mixin_include_arglist
|
98
82
|
args, keywords = [], {}
|
99
83
|
if try_tok(:lparen)
|
100
|
-
args, keywords, splat
|
84
|
+
args, keywords, splat = mixin_arglist || [[], {}]
|
101
85
|
assert_tok(:rparen)
|
102
86
|
end
|
103
87
|
assert_done
|
@@ -105,8 +89,7 @@ module Sass
|
|
105
89
|
args.each {|a| a.options = @options}
|
106
90
|
keywords.each {|k, v| v.options = @options}
|
107
91
|
splat.options = @options if splat
|
108
|
-
|
109
|
-
return args, keywords, splat, kwarg_splat
|
92
|
+
return args, keywords, splat
|
110
93
|
rescue Sass::SyntaxError => e
|
111
94
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
112
95
|
raise e
|
@@ -114,7 +97,7 @@ module Sass
|
|
114
97
|
|
115
98
|
# Parses the argument list for a mixin definition.
|
116
99
|
#
|
117
|
-
# @return [(Array<Script::
|
100
|
+
# @return [(Array<Script::Node>, Script::Node)]
|
118
101
|
# The root nodes of the arguments, and the splat argument.
|
119
102
|
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
|
120
103
|
def parse_mixin_definition_arglist
|
@@ -134,7 +117,7 @@ module Sass
|
|
134
117
|
|
135
118
|
# Parses the argument list for a function definition.
|
136
119
|
#
|
137
|
-
# @return [(Array<Script::
|
120
|
+
# @return [(Array<Script::Node>, Script::Node)]
|
138
121
|
# The root nodes of the arguments, and the splat argument.
|
139
122
|
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
|
140
123
|
def parse_function_definition_arglist
|
@@ -155,7 +138,7 @@ module Sass
|
|
155
138
|
# Parse a single string value, possibly containing interpolation.
|
156
139
|
# Doesn't assert that the scanner is finished after parsing.
|
157
140
|
#
|
158
|
-
# @return [Script::
|
141
|
+
# @return [Script::Node] The root node of the parse tree.
|
159
142
|
# @raise [Sass::SyntaxError] if the string isn't valid SassScript
|
160
143
|
def parse_string
|
161
144
|
unless (peek = @lexer.peek) &&
|
@@ -176,7 +159,7 @@ module Sass
|
|
176
159
|
# Parses a SassScript expression.
|
177
160
|
#
|
178
161
|
# @overload parse(str, line, offset, filename = nil)
|
179
|
-
# @return [Script::
|
162
|
+
# @return [Script::Node] The root node of the parse tree
|
180
163
|
# @see Parser#initialize
|
181
164
|
# @see Parser#parse
|
182
165
|
def self.parse(*args)
|
@@ -203,7 +186,7 @@ module Sass
|
|
203
186
|
PRECEDENCE.each_with_index do |e, i|
|
204
187
|
return i if Array(e).include?(op)
|
205
188
|
end
|
206
|
-
raise "[BUG] Unknown operator #{op
|
189
|
+
raise "[BUG] Unknown operator #{op}"
|
207
190
|
end
|
208
191
|
|
209
192
|
# Returns whether or not the given operation is associative.
|
@@ -222,18 +205,17 @@ module Sass
|
|
222
205
|
def production(name, sub, *ops)
|
223
206
|
class_eval <<RUBY, __FILE__, __LINE__ + 1
|
224
207
|
def #{name}
|
225
|
-
interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect})
|
226
|
-
return interp if interp
|
208
|
+
interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect}) and return interp
|
227
209
|
return unless e = #{sub}
|
228
|
-
while tok =
|
210
|
+
while tok = try_tok(#{ops.map {|o| o.inspect}.join(', ')})
|
229
211
|
if interp = try_op_before_interp(tok, e)
|
230
|
-
other_interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect}, interp)
|
231
|
-
return interp unless other_interp
|
212
|
+
return interp unless other_interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect}, interp)
|
232
213
|
return other_interp
|
233
214
|
end
|
234
215
|
|
235
|
-
|
236
|
-
|
216
|
+
line = @lexer.line
|
217
|
+
e = Operation.new(e, assert_expr(#{sub.inspect}), tok.type)
|
218
|
+
e.line = line
|
237
219
|
end
|
238
220
|
e
|
239
221
|
end
|
@@ -244,10 +226,11 @@ RUBY
|
|
244
226
|
class_eval <<RUBY, __FILE__, __LINE__ + 1
|
245
227
|
def unary_#{op}
|
246
228
|
return #{sub} unless tok = try_tok(:#{op})
|
247
|
-
interp = try_op_before_interp(tok)
|
248
|
-
|
249
|
-
|
250
|
-
|
229
|
+
interp = try_op_before_interp(tok) and return interp
|
230
|
+
line = @lexer.line
|
231
|
+
op = UnaryOperation.new(assert_expr(:unary_#{op}), :#{op})
|
232
|
+
op.line = line
|
233
|
+
op
|
251
234
|
end
|
252
235
|
RUBY
|
253
236
|
end
|
@@ -255,61 +238,21 @@ RUBY
|
|
255
238
|
|
256
239
|
private
|
257
240
|
|
258
|
-
def source_position
|
259
|
-
Sass::Source::Position.new(line, offset)
|
260
|
-
end
|
261
|
-
|
262
|
-
def range(start_pos, end_pos = source_position)
|
263
|
-
Sass::Source::Range.new(start_pos, end_pos, @options[:filename], @options[:importer])
|
264
|
-
end
|
265
|
-
|
266
241
|
# @private
|
267
242
|
def lexer_class; Lexer; end
|
268
243
|
|
269
|
-
def map
|
270
|
-
start_pos = source_position
|
271
|
-
e = interpolation
|
272
|
-
return unless e
|
273
|
-
return list e, start_pos unless @lexer.peek && @lexer.peek.type == :colon
|
274
|
-
|
275
|
-
pair = map_pair(e)
|
276
|
-
map = node(Sass::Script::Tree::MapLiteral.new([pair]), start_pos)
|
277
|
-
while try_tok(:comma)
|
278
|
-
pair = map_pair
|
279
|
-
return map unless pair
|
280
|
-
map.pairs << pair
|
281
|
-
end
|
282
|
-
map
|
283
|
-
end
|
284
|
-
|
285
|
-
def map_pair(key = nil)
|
286
|
-
return unless key ||= interpolation
|
287
|
-
assert_tok :colon
|
288
|
-
return key, assert_expr(:interpolation)
|
289
|
-
end
|
290
|
-
|
291
244
|
def expr
|
292
|
-
|
293
|
-
e = interpolation
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
def list(first, start_pos)
|
299
|
-
return first unless @lexer.peek && @lexer.peek.type == :comma
|
300
|
-
|
301
|
-
list = node(Sass::Script::Tree::ListLiteral.new([first], :comma), start_pos)
|
302
|
-
while (tok = try_tok(:comma))
|
303
|
-
element_before_interp = list.elements.length == 1 ? list.elements.first : list
|
304
|
-
if (interp = try_op_before_interp(tok, element_before_interp))
|
305
|
-
other_interp = try_ops_after_interp([:comma], :expr, interp)
|
306
|
-
return interp unless other_interp
|
245
|
+
line = @lexer.line
|
246
|
+
return unless e = interpolation
|
247
|
+
list = node(List.new([e], :comma), line)
|
248
|
+
while tok = try_tok(:comma)
|
249
|
+
if interp = try_op_before_interp(tok, list)
|
250
|
+
return interp unless other_interp = try_ops_after_interp([:comma], :expr, interp)
|
307
251
|
return other_interp
|
308
252
|
end
|
309
|
-
|
310
|
-
list.elements << e
|
253
|
+
list.value << assert_expr(:interpolation)
|
311
254
|
end
|
312
|
-
list
|
255
|
+
list.value.size == 1 ? list.value.first : list
|
313
256
|
end
|
314
257
|
|
315
258
|
production :equals, :interpolation, :single_eq
|
@@ -317,58 +260,47 @@ RUBY
|
|
317
260
|
def try_op_before_interp(op, prev = nil)
|
318
261
|
return unless @lexer.peek && @lexer.peek.type == :begin_interpolation
|
319
262
|
wb = @lexer.whitespace?(op)
|
320
|
-
str =
|
321
|
-
|
322
|
-
interp =
|
323
|
-
|
324
|
-
(prev || str).source_range.start_pos)
|
263
|
+
str = Script::String.new(Lexer::OPERATORS_REVERSE[op.type])
|
264
|
+
str.line = @lexer.line
|
265
|
+
interp = Script::Interpolation.new(prev, str, nil, wb, !:wa, :originally_text)
|
266
|
+
interp.line = @lexer.line
|
325
267
|
interpolation(interp)
|
326
268
|
end
|
327
269
|
|
328
270
|
def try_ops_after_interp(ops, name, prev = nil)
|
329
271
|
return unless @lexer.after_interpolation?
|
330
|
-
op =
|
331
|
-
|
332
|
-
interp = try_op_before_interp(op, prev)
|
333
|
-
return interp if interp
|
272
|
+
return unless op = try_tok(*ops)
|
273
|
+
interp = try_op_before_interp(op, prev) and return interp
|
334
274
|
|
335
275
|
wa = @lexer.whitespace?
|
336
|
-
str =
|
337
|
-
op.source_range)
|
276
|
+
str = Script::String.new(Lexer::OPERATORS_REVERSE[op.type])
|
338
277
|
str.line = @lexer.line
|
339
|
-
interp =
|
340
|
-
|
341
|
-
|
342
|
-
interp
|
278
|
+
interp = Script::Interpolation.new(prev, str, assert_expr(name), !:wb, wa, :originally_text)
|
279
|
+
interp.line = @lexer.line
|
280
|
+
return interp
|
343
281
|
end
|
344
282
|
|
345
283
|
def interpolation(first = space)
|
346
284
|
e = first
|
347
|
-
while
|
285
|
+
while interp = try_tok(:begin_interpolation)
|
348
286
|
wb = @lexer.whitespace?(interp)
|
349
|
-
|
350
|
-
|
287
|
+
line = @lexer.line
|
288
|
+
mid = parse_interpolated
|
351
289
|
wa = @lexer.whitespace?
|
352
|
-
e =
|
353
|
-
|
354
|
-
(e || mid).source_range.start_pos)
|
290
|
+
e = Script::Interpolation.new(e, mid, space, wb, wa)
|
291
|
+
e.line = line
|
355
292
|
end
|
356
293
|
e
|
357
294
|
end
|
358
295
|
|
359
296
|
def space
|
360
|
-
|
361
|
-
e = or_expr
|
362
|
-
return unless e
|
297
|
+
line = @lexer.line
|
298
|
+
return unless e = or_expr
|
363
299
|
arr = [e]
|
364
|
-
while
|
300
|
+
while e = or_expr
|
365
301
|
arr << e
|
366
302
|
end
|
367
|
-
|
368
|
-
arr.first
|
369
|
-
else
|
370
|
-
node(Sass::Script::Tree::ListLiteral.new(arr, :space), start_pos)
|
371
|
-
end
|
303
|
+
arr.size == 1 ? arr.first : node(List.new(arr, :space), line)
|
372
304
|
end
|
373
305
|
|
374
306
|
production :or_expr, :and_expr, :or
|
@@ -388,26 +320,24 @@ RUBY
|
|
388
320
|
return if @stop_at && @stop_at.include?(@lexer.peek.value)
|
389
321
|
|
390
322
|
name = @lexer.next
|
391
|
-
if
|
392
|
-
|
323
|
+
if color = Color::COLOR_NAMES[name.value.downcase]
|
324
|
+
node(Color.new(color))
|
393
325
|
elsif name.value == "true"
|
394
|
-
|
326
|
+
node(Script::Bool.new(true))
|
395
327
|
elsif name.value == "false"
|
396
|
-
|
328
|
+
node(Script::Bool.new(false))
|
397
329
|
elsif name.value == "null"
|
398
|
-
|
330
|
+
node(Script::Null.new)
|
399
331
|
else
|
400
|
-
|
332
|
+
node(Script::String.new(name.value, :identifier))
|
401
333
|
end
|
402
334
|
end
|
403
335
|
|
404
336
|
def funcall
|
405
|
-
tok = try_tok(:funcall)
|
406
|
-
|
407
|
-
args, keywords, splat, kwarg_splat = fn_arglist
|
337
|
+
return raw unless tok = try_tok(:funcall)
|
338
|
+
args, keywords, splat = fn_arglist || [[], {}]
|
408
339
|
assert_tok(:rparen)
|
409
|
-
node(Script::
|
410
|
-
tok.source_range.start_pos, source_position)
|
340
|
+
node(Script::Funcall.new(tok.value, args, keywords, splat))
|
411
341
|
end
|
412
342
|
|
413
343
|
def defn_arglist!(must_have_parens)
|
@@ -423,16 +353,15 @@ RUBY
|
|
423
353
|
must_have_default = false
|
424
354
|
loop do
|
425
355
|
c = assert_tok(:const)
|
426
|
-
var =
|
356
|
+
var = Script::Variable.new(c.value)
|
427
357
|
if try_tok(:colon)
|
428
358
|
val = assert_expr(:space)
|
429
359
|
must_have_default = true
|
360
|
+
elsif must_have_default
|
361
|
+
raise SyntaxError.new("Required argument #{var.inspect} must come before any optional arguments.")
|
430
362
|
elsif try_tok(:splat)
|
431
363
|
splat = var
|
432
364
|
break
|
433
|
-
elsif must_have_default
|
434
|
-
raise SyntaxError.new(
|
435
|
-
"Required argument #{var.inspect} must come before any optional arguments.")
|
436
365
|
end
|
437
366
|
res << [var, val]
|
438
367
|
break unless try_tok(:comma)
|
@@ -450,108 +379,88 @@ RUBY
|
|
450
379
|
end
|
451
380
|
|
452
381
|
def arglist(subexpr, description)
|
453
|
-
|
454
|
-
keywords = Sass::Util::NormalizedMap.new
|
455
|
-
e = send(subexpr)
|
382
|
+
return unless e = send(subexpr)
|
456
383
|
|
457
|
-
|
458
|
-
|
459
|
-
splat = nil
|
384
|
+
args = []
|
385
|
+
keywords = {}
|
460
386
|
loop do
|
461
387
|
if @lexer.peek && @lexer.peek.type == :colon
|
462
388
|
name = e
|
463
|
-
@lexer.expected!("comma") unless name.is_a?(
|
389
|
+
@lexer.expected!("comma") unless name.is_a?(Variable)
|
464
390
|
assert_tok(:colon)
|
465
391
|
value = assert_expr(subexpr, description)
|
466
392
|
|
467
|
-
if keywords[name.
|
393
|
+
if keywords[name.underscored_name]
|
468
394
|
raise SyntaxError.new("Keyword argument \"#{name.to_sass}\" passed more than once")
|
469
395
|
end
|
470
396
|
|
471
|
-
keywords[name.
|
397
|
+
keywords[name.underscored_name] = value
|
472
398
|
else
|
473
|
-
if
|
474
|
-
return args, keywords, splat, e if splat
|
475
|
-
splat, e = e, nil
|
476
|
-
elsif splat
|
477
|
-
raise SyntaxError.new("Only keyword arguments may follow variable arguments (...).")
|
478
|
-
elsif !keywords.empty?
|
399
|
+
if !keywords.empty?
|
479
400
|
raise SyntaxError.new("Positional arguments must come before keyword arguments.")
|
480
401
|
end
|
481
402
|
|
482
|
-
args
|
403
|
+
return args, keywords, e if try_tok(:splat)
|
404
|
+
args << e
|
483
405
|
end
|
484
406
|
|
485
|
-
return args, keywords
|
407
|
+
return args, keywords unless try_tok(:comma)
|
486
408
|
e = assert_expr(subexpr, description)
|
487
409
|
end
|
488
410
|
end
|
489
411
|
|
490
412
|
def raw
|
491
|
-
tok = try_tok(:raw)
|
492
|
-
|
493
|
-
literal_node(Script::Value::String.new(tok.value), tok.source_range)
|
413
|
+
return special_fun unless tok = try_tok(:raw)
|
414
|
+
node(Script::String.new(tok.value))
|
494
415
|
end
|
495
416
|
|
496
417
|
def special_fun
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
first.source_range.start_pos)
|
418
|
+
return paren unless tok = try_tok(:special_fun)
|
419
|
+
first = node(Script::String.new(tok.value.first))
|
420
|
+
Sass::Util.enum_slice(tok.value[1..-1], 2).inject(first) do |l, (i, r)|
|
421
|
+
Script::Interpolation.new(
|
422
|
+
l, i, r && node(Script::String.new(r)),
|
423
|
+
false, false)
|
424
|
+
end
|
505
425
|
end
|
506
426
|
|
507
427
|
def paren
|
508
428
|
return variable unless try_tok(:lparen)
|
509
429
|
was_in_parens = @in_parens
|
510
430
|
@in_parens = true
|
511
|
-
|
512
|
-
e =
|
513
|
-
end_pos = source_position
|
431
|
+
line = @lexer.line
|
432
|
+
e = expr
|
514
433
|
assert_tok(:rparen)
|
515
|
-
return e || node(
|
434
|
+
return e || node(List.new([], :space), line)
|
516
435
|
ensure
|
517
436
|
@in_parens = was_in_parens
|
518
437
|
end
|
519
438
|
|
520
439
|
def variable
|
521
|
-
|
522
|
-
c
|
523
|
-
return string unless c
|
524
|
-
node(Tree::Variable.new(*c.value), start_pos)
|
440
|
+
return string unless c = try_tok(:const)
|
441
|
+
node(Variable.new(*c.value))
|
525
442
|
end
|
526
443
|
|
527
444
|
def string
|
528
|
-
first = try_tok(:string)
|
529
|
-
return
|
530
|
-
|
531
|
-
|
532
|
-
mid = assert_expr :expr
|
533
|
-
assert_tok :end_interpolation
|
445
|
+
return number unless first = try_tok(:string)
|
446
|
+
return first.value unless try_tok(:begin_interpolation)
|
447
|
+
line = @lexer.line
|
448
|
+
mid = parse_interpolated
|
534
449
|
last = assert_expr(:string)
|
535
|
-
|
450
|
+
interp = StringInterpolation.new(first.value, mid, last)
|
451
|
+
interp.line = line
|
452
|
+
interp
|
536
453
|
end
|
537
454
|
|
538
455
|
def number
|
539
|
-
tok = try_tok(:number)
|
540
|
-
return selector unless tok
|
456
|
+
return literal unless tok = try_tok(:number)
|
541
457
|
num = tok.value
|
542
458
|
num.original = num.to_s unless @in_parens
|
543
|
-
|
544
|
-
end
|
545
|
-
|
546
|
-
def selector
|
547
|
-
tok = try_tok(:selector)
|
548
|
-
return literal unless tok
|
549
|
-
node(tok.value, tok.source_range.start_pos)
|
459
|
+
num
|
550
460
|
end
|
551
461
|
|
552
462
|
def literal
|
553
|
-
t = try_tok(:color)
|
554
|
-
return literal_node(t.value, t.source_range) if t
|
463
|
+
(t = try_tok(:color)) && (return t.value)
|
555
464
|
end
|
556
465
|
|
557
466
|
# It would be possible to have unified #assert and #try methods,
|
@@ -562,37 +471,20 @@ RUBY
|
|
562
471
|
:default => "expression (e.g. 1px, bold)",
|
563
472
|
:mixin_arglist => "mixin argument",
|
564
473
|
:fn_arglist => "function argument",
|
565
|
-
:splat => "...",
|
566
|
-
:special_fun => '")"',
|
567
474
|
}
|
568
475
|
|
569
476
|
def assert_expr(name, expected = nil)
|
570
|
-
e = send(name)
|
571
|
-
return e if e
|
477
|
+
(e = send(name)) && (return e)
|
572
478
|
@lexer.expected!(expected || EXPR_NAMES[name] || EXPR_NAMES[:default])
|
573
479
|
end
|
574
480
|
|
575
|
-
def assert_tok(
|
576
|
-
|
577
|
-
t = try_tok(name)
|
578
|
-
return t if t
|
579
|
-
@lexer.expected!(Lexer::TOKEN_NAMES[name] || name.to_s)
|
580
|
-
end
|
581
|
-
|
582
|
-
def assert_toks(*names)
|
583
|
-
t = try_toks(*names)
|
584
|
-
return t if t
|
481
|
+
def assert_tok(*names)
|
482
|
+
(t = try_tok(*names)) && (return t)
|
585
483
|
@lexer.expected!(names.map {|tok| Lexer::TOKEN_NAMES[tok] || tok}.join(" or "))
|
586
484
|
end
|
587
485
|
|
588
|
-
def try_tok(
|
589
|
-
|
590
|
-
peeked = @lexer.peek
|
591
|
-
peeked && name == peeked.type && @lexer.next
|
592
|
-
end
|
593
|
-
|
594
|
-
def try_toks(*names)
|
595
|
-
peeked = @lexer.peek
|
486
|
+
def try_tok(*names)
|
487
|
+
peeked = @lexer.peek
|
596
488
|
peeked && names.include?(peeked.type) && @lexer.next
|
597
489
|
end
|
598
490
|
|
@@ -601,35 +493,8 @@ RUBY
|
|
601
493
|
@lexer.expected!(EXPR_NAMES[:default])
|
602
494
|
end
|
603
495
|
|
604
|
-
|
605
|
-
|
606
|
-
# @param source_range [Sass::Source::Range]
|
607
|
-
# @overload node(value, start_pos, end_pos = source_position)
|
608
|
-
# @param value [Sass::Script::Value::Base]
|
609
|
-
# @param start_pos [Sass::Source::Position]
|
610
|
-
# @param end_pos [Sass::Source::Position]
|
611
|
-
def literal_node(value, source_range_or_start_pos, end_pos = source_position)
|
612
|
-
node(Sass::Script::Tree::Literal.new(value), source_range_or_start_pos, end_pos)
|
613
|
-
end
|
614
|
-
|
615
|
-
# @overload node(node, source_range)
|
616
|
-
# @param node [Sass::Script::Tree::Node]
|
617
|
-
# @param source_range [Sass::Source::Range]
|
618
|
-
# @overload node(node, start_pos, end_pos = source_position)
|
619
|
-
# @param node [Sass::Script::Tree::Node]
|
620
|
-
# @param start_pos [Sass::Source::Position]
|
621
|
-
# @param end_pos [Sass::Source::Position]
|
622
|
-
def node(node, source_range_or_start_pos, end_pos = source_position)
|
623
|
-
source_range =
|
624
|
-
if source_range_or_start_pos.is_a?(Sass::Source::Range)
|
625
|
-
source_range_or_start_pos
|
626
|
-
else
|
627
|
-
range(source_range_or_start_pos, end_pos)
|
628
|
-
end
|
629
|
-
|
630
|
-
node.line = source_range.start_pos.line
|
631
|
-
node.source_range = source_range
|
632
|
-
node.filename = @options[:filename]
|
496
|
+
def node(node, line = @lexer.line)
|
497
|
+
node.line = line
|
633
498
|
node
|
634
499
|
end
|
635
500
|
end
|