haml-edge 2.3.179 → 2.3.180
Sign up to get free protection for your applications and to get access to all the features.
- data/EDGE_GEM_VERSION +1 -1
- data/README.md +88 -149
- data/VERSION +1 -1
- data/bin/css2sass +7 -1
- data/bin/sass-convert +7 -0
- data/lib/haml/exec.rb +95 -22
- data/lib/haml/template.rb +1 -1
- data/lib/haml/util.rb +50 -0
- data/lib/sass.rb +1 -1
- data/lib/sass/css.rb +38 -210
- data/lib/sass/engine.rb +121 -47
- data/lib/sass/files.rb +28 -19
- data/lib/sass/plugin.rb +32 -43
- data/lib/sass/repl.rb +1 -1
- data/lib/sass/script.rb +25 -6
- data/lib/sass/script/bool.rb +1 -0
- data/lib/sass/script/color.rb +2 -2
- data/lib/sass/script/css_lexer.rb +22 -0
- data/lib/sass/script/css_parser.rb +28 -0
- data/lib/sass/script/funcall.rb +17 -9
- data/lib/sass/script/functions.rb +46 -1
- data/lib/sass/script/interpolation.rb +42 -0
- data/lib/sass/script/lexer.rb +142 -34
- data/lib/sass/script/literal.rb +28 -12
- data/lib/sass/script/node.rb +57 -1
- data/lib/sass/script/number.rb +18 -3
- data/lib/sass/script/operation.rb +44 -8
- data/lib/sass/script/parser.rb +149 -24
- data/lib/sass/script/string.rb +50 -2
- data/lib/sass/script/unary_operation.rb +25 -10
- data/lib/sass/script/variable.rb +20 -11
- data/lib/sass/scss.rb +14 -0
- data/lib/sass/scss/css_parser.rb +39 -0
- data/lib/sass/scss/parser.rb +683 -0
- data/lib/sass/scss/rx.rb +112 -0
- data/lib/sass/scss/script_lexer.rb +13 -0
- data/lib/sass/scss/script_parser.rb +25 -0
- data/lib/sass/tree/comment_node.rb +58 -16
- data/lib/sass/tree/debug_node.rb +7 -2
- data/lib/sass/tree/directive_node.rb +38 -34
- data/lib/sass/tree/for_node.rb +6 -0
- data/lib/sass/tree/if_node.rb +13 -0
- data/lib/sass/tree/import_node.rb +26 -7
- data/lib/sass/tree/mixin_def_node.rb +18 -0
- data/lib/sass/tree/mixin_node.rb +16 -1
- data/lib/sass/tree/node.rb +98 -27
- data/lib/sass/tree/prop_node.rb +97 -20
- data/lib/sass/tree/root_node.rb +37 -0
- data/lib/sass/tree/rule_node.rb +88 -60
- data/lib/sass/tree/variable_node.rb +9 -5
- data/lib/sass/tree/while_node.rb +4 -0
- data/test/haml/results/filters.xhtml +1 -1
- data/test/haml/util_test.rb +28 -0
- data/test/sass/conversion_test.rb +884 -0
- data/test/sass/css2sass_test.rb +46 -21
- data/test/sass/engine_test.rb +680 -160
- data/test/sass/functions_test.rb +27 -0
- data/test/sass/more_results/more_import.css +1 -1
- data/test/sass/more_templates/more_import.sass +3 -3
- data/test/sass/plugin_test.rb +28 -8
- data/test/sass/results/compact.css +1 -1
- data/test/sass/results/complex.css +5 -5
- data/test/sass/results/compressed.css +1 -1
- data/test/sass/results/expanded.css +1 -1
- data/test/sass/results/import.css +3 -1
- data/test/sass/results/mixins.css +12 -12
- data/test/sass/results/nested.css +1 -1
- data/test/sass/results/parent_ref.css +4 -4
- data/test/sass/results/script.css +3 -3
- data/test/sass/results/scss_import.css +15 -0
- data/test/sass/results/scss_importee.css +2 -0
- data/test/sass/script_conversion_test.rb +153 -0
- data/test/sass/script_test.rb +44 -54
- data/test/sass/scss/css_test.rb +811 -0
- data/test/sass/scss/rx_test.rb +156 -0
- data/test/sass/scss/scss_test.rb +871 -0
- data/test/sass/scss/test_helper.rb +37 -0
- data/test/sass/templates/alt.sass +2 -2
- data/test/sass/templates/bork1.sass +1 -1
- data/test/sass/templates/import.sass +4 -4
- data/test/sass/templates/importee.sass +3 -3
- data/test/sass/templates/line_numbers.sass +1 -1
- data/test/sass/templates/mixins.sass +2 -2
- data/test/sass/templates/nested_mixin_bork.sass +1 -1
- data/test/sass/templates/options.sass +1 -1
- data/test/sass/templates/parent_ref.sass +2 -2
- data/test/sass/templates/script.sass +69 -69
- data/test/sass/templates/scss_import.scss +10 -0
- data/test/sass/templates/scss_importee.scss +1 -0
- data/test/sass/templates/units.sass +10 -10
- data/test/test_helper.rb +4 -4
- metadata +27 -2
@@ -2,7 +2,7 @@ module Sass::Script
|
|
2
2
|
# Methods in this module are accessible from the SassScript context.
|
3
3
|
# For example, you can write
|
4
4
|
#
|
5
|
-
#
|
5
|
+
# $color = hsl(120deg, 100%, 50%)
|
6
6
|
#
|
7
7
|
# and it will call {Sass::Script::Functions#hsl}.
|
8
8
|
#
|
@@ -80,6 +80,14 @@ module Sass::Script
|
|
80
80
|
# \{#transparentize} / \{#fade_out #fade-out}
|
81
81
|
# : Makes a color more transparent.
|
82
82
|
#
|
83
|
+
# ## String Functions
|
84
|
+
#
|
85
|
+
# \{#unquote}
|
86
|
+
# : Removes the quotes from a string.
|
87
|
+
#
|
88
|
+
# \{#quote}
|
89
|
+
# : Adds quotes to a string.
|
90
|
+
#
|
83
91
|
# ## Number Functions
|
84
92
|
#
|
85
93
|
# \{#percentage}
|
@@ -170,6 +178,8 @@ module Sass::Script
|
|
170
178
|
# assert_type value, :Number
|
171
179
|
#
|
172
180
|
# Valid types are `:Bool`, `:Color`, `:Number`, and `:String`.
|
181
|
+
# Note that `:String` will match both double-quoted strings
|
182
|
+
# and unquoted identifiers.
|
173
183
|
#
|
174
184
|
# @param value [Sass::Script::Literal] A SassScript value
|
175
185
|
# @param type [Symbol] The name of the type the value is expected to be
|
@@ -608,6 +618,36 @@ module Sass::Script
|
|
608
618
|
adjust_hue color, Number.new(180)
|
609
619
|
end
|
610
620
|
|
621
|
+
# Removes quotes from a string if the string is quoted,
|
622
|
+
# or returns the same string if it's not.
|
623
|
+
#
|
624
|
+
# @param str [String]
|
625
|
+
# @return [String]
|
626
|
+
# @raise [ArgumentError] if `str` isn't a string
|
627
|
+
# @see #quote
|
628
|
+
# @example
|
629
|
+
# unquote("foo") => foo
|
630
|
+
# unquote(foo) => foo
|
631
|
+
def unquote(str)
|
632
|
+
assert_type str, :String
|
633
|
+
Sass::Script::String.new(str.value, :identifier)
|
634
|
+
end
|
635
|
+
|
636
|
+
# Add quotes to a string if the string isn't quoted,
|
637
|
+
# or returns the same string if it is.
|
638
|
+
#
|
639
|
+
# @param str [String]
|
640
|
+
# @return [String]
|
641
|
+
# @raise [ArgumentError] if `str` isn't a string
|
642
|
+
# @see #unquote
|
643
|
+
# @example
|
644
|
+
# quote("foo") => "foo"
|
645
|
+
# quote(foo) => "foo"
|
646
|
+
def quote(str)
|
647
|
+
assert_type str, :String
|
648
|
+
Sass::Script::String.new(str.value, :string)
|
649
|
+
end
|
650
|
+
|
611
651
|
# Converts a decimal number to a percentage.
|
612
652
|
# For example:
|
613
653
|
#
|
@@ -675,6 +715,11 @@ module Sass::Script
|
|
675
715
|
numeric_transformation(value) {|n| n.abs}
|
676
716
|
end
|
677
717
|
|
718
|
+
def unquote(value)
|
719
|
+
assert_type value, :String
|
720
|
+
Sass::Script::String.new(value.value)
|
721
|
+
end
|
722
|
+
|
678
723
|
private
|
679
724
|
|
680
725
|
# This method implements the pattern of transforming a numeric value into
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Sass::Script
|
2
|
+
class Interpolation < Node
|
3
|
+
def initialize(before, mid, after, wb, wa)
|
4
|
+
@before = before
|
5
|
+
@mid = mid
|
6
|
+
@after = after
|
7
|
+
@whitespace_before = wb
|
8
|
+
@whitespace_after = wa
|
9
|
+
end
|
10
|
+
|
11
|
+
def inspect
|
12
|
+
"(interpolation #{@before.inspect} #{@mid.inspect} #{after.inspect})"
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_sass
|
16
|
+
res = ""
|
17
|
+
res << @before.to_sass if @before
|
18
|
+
res << ' ' if @before && @whitespace_before
|
19
|
+
res << '#{' << @mid.to_sass << '}'
|
20
|
+
res << ' ' if @after && @whitespace_after
|
21
|
+
res << @after.to_sass if @after
|
22
|
+
res
|
23
|
+
end
|
24
|
+
|
25
|
+
def children
|
26
|
+
[@before, @mid, @after].compact
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def _perform(environment)
|
32
|
+
res = ""
|
33
|
+
res << @before.perform(environment).to_s if @before
|
34
|
+
res << " " if @before && @whitespace_before
|
35
|
+
val = @mid.perform(environment)
|
36
|
+
res << (val.is_a?(Sass::Script::String) ? val.value : val.to_s)
|
37
|
+
res << " " if @after && @whitespace_after
|
38
|
+
res << @after.perform(environment).to_s if @after
|
39
|
+
Sass::Script::String.new(res)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/sass/script/lexer.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'sass/scss/rx'
|
2
|
+
|
1
3
|
require 'strscan'
|
2
4
|
|
3
5
|
module Sass
|
@@ -6,6 +8,8 @@ module Sass
|
|
6
8
|
# It takes a raw string and converts it to individual tokens
|
7
9
|
# that are easier to parse.
|
8
10
|
class Lexer
|
11
|
+
include Sass::SCSS::RX
|
12
|
+
|
9
13
|
# A struct containing information about an individual token.
|
10
14
|
#
|
11
15
|
# `type`: \[`Symbol`\]
|
@@ -19,7 +23,21 @@ module Sass
|
|
19
23
|
#
|
20
24
|
# `offset`: \[`Fixnum`\]
|
21
25
|
# : The number of bytes into the line the SassScript token appeared.
|
22
|
-
|
26
|
+
#
|
27
|
+
# `pos`: \[`Fixnum`\]
|
28
|
+
# : The scanner position at which the SassScript token appeared.
|
29
|
+
Token = Struct.new(:type, :value, :line, :offset, :pos)
|
30
|
+
|
31
|
+
# The line number of the lexer's current position.
|
32
|
+
#
|
33
|
+
# @return [Fixnum]
|
34
|
+
attr_reader :line
|
35
|
+
|
36
|
+
# The number of bytes into the current line
|
37
|
+
# of the lexer's current position.
|
38
|
+
#
|
39
|
+
# @return [Fixnum]
|
40
|
+
attr_reader :offset
|
23
41
|
|
24
42
|
# A hash from operator strings to the corresponding token types.
|
25
43
|
# @private
|
@@ -30,6 +48,7 @@ module Sass
|
|
30
48
|
'/' => :div,
|
31
49
|
'%' => :mod,
|
32
50
|
'=' => :single_eq,
|
51
|
+
':' => :colon,
|
33
52
|
'(' => :lparen,
|
34
53
|
')' => :rparen,
|
35
54
|
',' => :comma,
|
@@ -44,23 +63,43 @@ module Sass
|
|
44
63
|
'<' => :lt,
|
45
64
|
'#{' => :begin_interpolation,
|
46
65
|
'}' => :end_interpolation,
|
66
|
+
';' => :semicolon,
|
67
|
+
'{' => :lcurly,
|
47
68
|
}
|
48
69
|
|
70
|
+
# @private
|
71
|
+
OPERATORS_REVERSE = Haml::Util.map_hash(OPERATORS) {|k, v| [v, k]}
|
72
|
+
|
73
|
+
# @private
|
74
|
+
TOKEN_NAMES = Haml::Util.map_hash(OPERATORS_REVERSE) {|k, v| [k, v.inspect]}.merge({
|
75
|
+
:const => "variable (e.g. $foo)",
|
76
|
+
:ident => "identifier (e.g. middle)",
|
77
|
+
:bool => "boolean (e.g. true, false)",
|
78
|
+
})
|
79
|
+
|
49
80
|
# A list of operator strings ordered with longer names first
|
50
81
|
# so that `>` and `<` don't clobber `>=` and `<=`.
|
51
82
|
# @private
|
52
83
|
OP_NAMES = OPERATORS.keys.sort_by {|o| -o.size}
|
53
84
|
|
85
|
+
# A sub-list of {OP_NAMES} that only includes operators
|
86
|
+
# with identifier names.
|
87
|
+
# @private
|
88
|
+
IDENT_OP_NAMES = OP_NAMES.select {|k, v| k =~ /^\w+/}
|
89
|
+
|
54
90
|
# A hash of regular expressions that are used for tokenizing.
|
55
91
|
# @private
|
56
92
|
REGULAR_EXPRESSIONS = {
|
57
|
-
:whitespace => /\s
|
58
|
-
:
|
59
|
-
:
|
93
|
+
:whitespace => /\s+/,
|
94
|
+
:comment => COMMENT,
|
95
|
+
:single_line_comment => SINGLE_LINE_COMMENT,
|
96
|
+
:variable => /([!\$])(#{IDENT})/,
|
97
|
+
:ident => IDENT,
|
60
98
|
:number => /(-)?(?:(\d*\.\d+)|(\d+))([a-zA-Z%]+)?/,
|
61
|
-
:color =>
|
99
|
+
:color => HEXCOLOR,
|
62
100
|
:bool => /(true|false)\b/,
|
63
|
-
:
|
101
|
+
:ident_op => %r{(#{Regexp.union(*IDENT_OP_NAMES.map{|s| Regexp.new(Regexp.escape(s) + '(?:\b|$)')})})},
|
102
|
+
:op => %r{(#{Regexp.union(*OP_NAMES)})},
|
64
103
|
}
|
65
104
|
|
66
105
|
class << self
|
@@ -109,6 +148,18 @@ module Sass
|
|
109
148
|
return tok
|
110
149
|
end
|
111
150
|
|
151
|
+
# Returns whether or not there's whitespace before the next token.
|
152
|
+
#
|
153
|
+
# @return [Boolean]
|
154
|
+
def whitespace?(tok = @tok)
|
155
|
+
if tok
|
156
|
+
@scanner.string[0...tok.pos] =~ /\s$/
|
157
|
+
else
|
158
|
+
@scanner.string[@scanner.pos, 1] =~ /^\s/ ||
|
159
|
+
@scanner.string[@scanner.pos - 1, 1] =~ /\s$/
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
112
163
|
# Returns the next token without moving the lexer forward.
|
113
164
|
#
|
114
165
|
# @return [Token] The next token
|
@@ -116,83 +167,140 @@ module Sass
|
|
116
167
|
@tok ||= read_token
|
117
168
|
end
|
118
169
|
|
170
|
+
# Rewinds the underlying StringScanner
|
171
|
+
# to before the token returned by \{#peek}.
|
172
|
+
def unpeek!
|
173
|
+
@scanner.pos = @tok.pos if @tok
|
174
|
+
end
|
175
|
+
|
119
176
|
# @return [Boolean] Whether or not there's more source text to lex.
|
120
177
|
def done?
|
121
|
-
whitespace unless after_interpolation?
|
178
|
+
whitespace unless after_interpolation? && @interpolation_stack.last
|
122
179
|
@scanner.eos? && @tok.nil?
|
123
180
|
end
|
124
181
|
|
182
|
+
def expected!(name)
|
183
|
+
unpeek!
|
184
|
+
Sass::SCSS::Parser.expected(@scanner, name, @line)
|
185
|
+
end
|
186
|
+
|
187
|
+
def str
|
188
|
+
old_pos = @tok ? @tok.pos : @scanner.pos
|
189
|
+
yield
|
190
|
+
new_pos = @tok ? @tok.pos : @scanner.pos
|
191
|
+
@scanner.string[old_pos...new_pos]
|
192
|
+
end
|
193
|
+
|
125
194
|
private
|
126
195
|
|
127
196
|
def read_token
|
128
197
|
return if done?
|
198
|
+
return unless value = token
|
129
199
|
|
130
|
-
value =
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
Token.new(value.first, value.last, @line, last_match_position)
|
200
|
+
value.last.line = @line if value.last.is_a?(Script::Node)
|
201
|
+
Token.new(value.first, value.last, @line,
|
202
|
+
current_position - @scanner.matched_size,
|
203
|
+
@scanner.pos - @scanner.matched_size)
|
135
204
|
end
|
136
205
|
|
137
206
|
def whitespace
|
138
|
-
|
207
|
+
nil while scan(REGULAR_EXPRESSIONS[:whitespace]) ||
|
208
|
+
scan(REGULAR_EXPRESSIONS[:comment]) ||
|
209
|
+
scan(REGULAR_EXPRESSIONS[:single_line_comment])
|
139
210
|
end
|
140
211
|
|
141
212
|
def token
|
142
|
-
|
143
|
-
|
213
|
+
if after_interpolation? && (interp_type = @interpolation_stack.pop)
|
214
|
+
return string(interp_type, true)
|
215
|
+
end
|
216
|
+
|
217
|
+
variable || string(:double, false) || string(:single, false) || number ||
|
218
|
+
color || bool || raw(URI) || raw(UNICODERANGE) || special_fun ||
|
219
|
+
ident_op || ident || op
|
144
220
|
end
|
145
221
|
|
146
222
|
def variable
|
147
|
-
|
148
|
-
|
223
|
+
_variable(REGULAR_EXPRESSIONS[:variable])
|
224
|
+
end
|
225
|
+
|
226
|
+
def _variable(rx)
|
227
|
+
line = @line
|
228
|
+
offset = @offset
|
229
|
+
return unless scan(rx)
|
230
|
+
if @scanner[1] == '!' && @scanner[2] != 'important'
|
231
|
+
Script.var_warning(@scanner[2], line, offset + 1, @options[:filename])
|
232
|
+
end
|
233
|
+
|
234
|
+
[:const, @scanner[2]]
|
149
235
|
end
|
150
236
|
|
151
237
|
def ident
|
152
|
-
return unless s =
|
238
|
+
return unless s = scan(REGULAR_EXPRESSIONS[:ident])
|
153
239
|
[:ident, s.gsub(/\\(.)/, '\1')]
|
154
240
|
end
|
155
241
|
|
156
242
|
def string(re, open)
|
157
|
-
return unless
|
243
|
+
return unless scan(STRING_REGULAR_EXPRESSIONS[[re, open]])
|
158
244
|
@interpolation_stack << re if @scanner[2].empty? # Started an interpolated section
|
159
|
-
[:string, Script::String.new(@scanner[1].gsub(/\\([^0-9a-f])/, '\1').gsub(/\\([0-9a-f]{1,4})/, "\\\\\\1"))]
|
245
|
+
[:string, Script::String.new(@scanner[1].gsub(/\\([^0-9a-f])/, '\1').gsub(/\\([0-9a-f]{1,4})/, "\\\\\\1"), :string)]
|
160
246
|
end
|
161
247
|
|
162
248
|
def number
|
163
|
-
return unless
|
249
|
+
return unless scan(REGULAR_EXPRESSIONS[:number])
|
164
250
|
value = @scanner[2] ? @scanner[2].to_f : @scanner[3].to_i
|
165
251
|
value = -value if @scanner[1]
|
166
252
|
[:number, Script::Number.new(value, Array(@scanner[4]))]
|
167
253
|
end
|
168
254
|
|
169
255
|
def color
|
170
|
-
return unless
|
171
|
-
value =
|
172
|
-
|
173
|
-
else
|
174
|
-
(1..3).map {|i| @scanner[i]}.map {|num| num.ljust(2, num).to_i(16)}
|
175
|
-
end
|
256
|
+
return unless s = scan(REGULAR_EXPRESSIONS[:color])
|
257
|
+
value = s.scan(/^#(..?)(..?)(..?)$/).first.
|
258
|
+
map {|num| num.ljust(2, num).to_i(16)}
|
176
259
|
[:color, Script::Color.new(value)]
|
177
260
|
end
|
178
261
|
|
179
262
|
def bool
|
180
|
-
return unless s =
|
263
|
+
return unless s = scan(REGULAR_EXPRESSIONS[:bool])
|
181
264
|
[:bool, Script::Bool.new(s == 'true')]
|
182
265
|
end
|
183
266
|
|
267
|
+
def special_fun
|
268
|
+
return unless str1 = scan(/(calc|expression|progid:[a-z\.]*)\(/i)
|
269
|
+
str2, _ = Haml::Shared.balance(@scanner, ?(, ?), 1)
|
270
|
+
c = str2.count("\n")
|
271
|
+
@line += c
|
272
|
+
@offset = (c == 0 ? @offset + str2.size : str2[/\n(.*)/, 1].size)
|
273
|
+
[:special_fun,
|
274
|
+
Haml::Util.merge_adjacent_strings(
|
275
|
+
[str1] + Sass::Engine.parse_interp(str2, @line, @options))]
|
276
|
+
end
|
277
|
+
|
278
|
+
def ident_op
|
279
|
+
return unless op = scan(REGULAR_EXPRESSIONS[:ident_op])
|
280
|
+
[OPERATORS[op]]
|
281
|
+
end
|
282
|
+
|
184
283
|
def op
|
185
|
-
|
186
|
-
|
284
|
+
return unless op = scan(REGULAR_EXPRESSIONS[:op])
|
285
|
+
@interpolation_stack << nil if op == :begin_interpolation
|
187
286
|
[OPERATORS[op]]
|
188
287
|
end
|
189
288
|
|
190
|
-
def
|
191
|
-
|
289
|
+
def raw(rx)
|
290
|
+
return unless val = scan(rx)
|
291
|
+
[:raw, val]
|
292
|
+
end
|
293
|
+
|
294
|
+
def scan(re)
|
295
|
+
return unless str = @scanner.scan(re)
|
296
|
+
c = str.count("\n")
|
297
|
+
@line += c
|
298
|
+
@offset = (c == 0 ? @offset + str.size : str[/\n(.*)/, 1].size)
|
299
|
+
str
|
192
300
|
end
|
193
301
|
|
194
|
-
def
|
195
|
-
|
302
|
+
def current_position
|
303
|
+
@offset + 1
|
196
304
|
end
|
197
305
|
|
198
306
|
def after_interpolation?
|
data/lib/sass/script/literal.rb
CHANGED
@@ -21,14 +21,7 @@ module Sass::Script
|
|
21
21
|
# @param value [Object] The object for \{#value}
|
22
22
|
def initialize(value = nil)
|
23
23
|
@value = value
|
24
|
-
|
25
|
-
|
26
|
-
# Evaluates the literal.
|
27
|
-
#
|
28
|
-
# @param environment [Sass::Environment] The environment in which to evaluate the SassScript
|
29
|
-
# @return [Literal] This literal
|
30
|
-
def perform(environment)
|
31
|
-
self
|
24
|
+
super()
|
32
25
|
end
|
33
26
|
|
34
27
|
# Returns an empty array.
|
@@ -109,7 +102,7 @@ MSG
|
|
109
102
|
Sass::Script::Bool.new(!to_bool)
|
110
103
|
end
|
111
104
|
|
112
|
-
# The SassScript default operation (e.g.
|
105
|
+
# The SassScript default operation (e.g. `$a $b`, `"foo" "bar"`).
|
113
106
|
#
|
114
107
|
# @param other [Literal] The right-hand side of the operator
|
115
108
|
# @return [Script::String] A string containing both literals
|
@@ -118,7 +111,7 @@ MSG
|
|
118
111
|
Sass::Script::String.new("#{self.to_s} #{other.to_s}")
|
119
112
|
end
|
120
113
|
|
121
|
-
# The SassScript `,` operation (e.g.
|
114
|
+
# The SassScript `,` operation (e.g. `$a, $b`, `"foo", "bar"`).
|
122
115
|
#
|
123
116
|
# @param other [Literal] The right-hand side of the operator
|
124
117
|
# @return [Script::String] A string containing both literals
|
@@ -133,6 +126,9 @@ MSG
|
|
133
126
|
# @return [Script::String] A string containing both literals
|
134
127
|
# without any separation
|
135
128
|
def plus(other)
|
129
|
+
if other.is_a?(Sass::Script::String)
|
130
|
+
return Sass::Script::String.new(self.to_s + other.value, other.type)
|
131
|
+
end
|
136
132
|
Sass::Script::String.new(self.to_s + other.to_s)
|
137
133
|
end
|
138
134
|
|
@@ -154,7 +150,16 @@ MSG
|
|
154
150
|
Sass::Script::String.new("#{self.to_s}/#{other.to_s}")
|
155
151
|
end
|
156
152
|
|
157
|
-
# The SassScript unary
|
153
|
+
# The SassScript unary `+` operation (e.g. `+$a`).
|
154
|
+
#
|
155
|
+
# @param other [Literal] The right-hand side of the operator
|
156
|
+
# @return [Script::String] A string containing the literal
|
157
|
+
# preceded by `"+"`
|
158
|
+
def unary_plus
|
159
|
+
Sass::Script::String.new("+#{self.to_s}")
|
160
|
+
end
|
161
|
+
|
162
|
+
# The SassScript unary `-` operation (e.g. `-$a`).
|
158
163
|
#
|
159
164
|
# @param other [Literal] The right-hand side of the operator
|
160
165
|
# @return [Script::String] A string containing the literal
|
@@ -163,7 +168,7 @@ MSG
|
|
163
168
|
Sass::Script::String.new("-#{self.to_s}")
|
164
169
|
end
|
165
170
|
|
166
|
-
# The SassScript unary `/` operation (e.g.
|
171
|
+
# The SassScript unary `/` operation (e.g. `/$a`).
|
167
172
|
#
|
168
173
|
# @param other [Literal] The right-hand side of the operator
|
169
174
|
# @return [Script::String] A string containing the literal
|
@@ -206,5 +211,16 @@ MSG
|
|
206
211
|
def to_s
|
207
212
|
raise Sass::SyntaxError.new("[BUG] All subclasses of Sass::Literal must implement #to_s.")
|
208
213
|
end
|
214
|
+
alias_method :to_sass, :to_s
|
215
|
+
|
216
|
+
protected
|
217
|
+
|
218
|
+
# Evaluates the literal.
|
219
|
+
#
|
220
|
+
# @param environment [Sass::Environment] The environment in which to evaluate the SassScript
|
221
|
+
# @return [Literal] This literal
|
222
|
+
def _perform(environment)
|
223
|
+
self
|
224
|
+
end
|
209
225
|
end
|
210
226
|
end
|