haml-edge 2.3.179 → 2.3.180

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.
Files changed (92) hide show
  1. data/EDGE_GEM_VERSION +1 -1
  2. data/README.md +88 -149
  3. data/VERSION +1 -1
  4. data/bin/css2sass +7 -1
  5. data/bin/sass-convert +7 -0
  6. data/lib/haml/exec.rb +95 -22
  7. data/lib/haml/template.rb +1 -1
  8. data/lib/haml/util.rb +50 -0
  9. data/lib/sass.rb +1 -1
  10. data/lib/sass/css.rb +38 -210
  11. data/lib/sass/engine.rb +121 -47
  12. data/lib/sass/files.rb +28 -19
  13. data/lib/sass/plugin.rb +32 -43
  14. data/lib/sass/repl.rb +1 -1
  15. data/lib/sass/script.rb +25 -6
  16. data/lib/sass/script/bool.rb +1 -0
  17. data/lib/sass/script/color.rb +2 -2
  18. data/lib/sass/script/css_lexer.rb +22 -0
  19. data/lib/sass/script/css_parser.rb +28 -0
  20. data/lib/sass/script/funcall.rb +17 -9
  21. data/lib/sass/script/functions.rb +46 -1
  22. data/lib/sass/script/interpolation.rb +42 -0
  23. data/lib/sass/script/lexer.rb +142 -34
  24. data/lib/sass/script/literal.rb +28 -12
  25. data/lib/sass/script/node.rb +57 -1
  26. data/lib/sass/script/number.rb +18 -3
  27. data/lib/sass/script/operation.rb +44 -8
  28. data/lib/sass/script/parser.rb +149 -24
  29. data/lib/sass/script/string.rb +50 -2
  30. data/lib/sass/script/unary_operation.rb +25 -10
  31. data/lib/sass/script/variable.rb +20 -11
  32. data/lib/sass/scss.rb +14 -0
  33. data/lib/sass/scss/css_parser.rb +39 -0
  34. data/lib/sass/scss/parser.rb +683 -0
  35. data/lib/sass/scss/rx.rb +112 -0
  36. data/lib/sass/scss/script_lexer.rb +13 -0
  37. data/lib/sass/scss/script_parser.rb +25 -0
  38. data/lib/sass/tree/comment_node.rb +58 -16
  39. data/lib/sass/tree/debug_node.rb +7 -2
  40. data/lib/sass/tree/directive_node.rb +38 -34
  41. data/lib/sass/tree/for_node.rb +6 -0
  42. data/lib/sass/tree/if_node.rb +13 -0
  43. data/lib/sass/tree/import_node.rb +26 -7
  44. data/lib/sass/tree/mixin_def_node.rb +18 -0
  45. data/lib/sass/tree/mixin_node.rb +16 -1
  46. data/lib/sass/tree/node.rb +98 -27
  47. data/lib/sass/tree/prop_node.rb +97 -20
  48. data/lib/sass/tree/root_node.rb +37 -0
  49. data/lib/sass/tree/rule_node.rb +88 -60
  50. data/lib/sass/tree/variable_node.rb +9 -5
  51. data/lib/sass/tree/while_node.rb +4 -0
  52. data/test/haml/results/filters.xhtml +1 -1
  53. data/test/haml/util_test.rb +28 -0
  54. data/test/sass/conversion_test.rb +884 -0
  55. data/test/sass/css2sass_test.rb +46 -21
  56. data/test/sass/engine_test.rb +680 -160
  57. data/test/sass/functions_test.rb +27 -0
  58. data/test/sass/more_results/more_import.css +1 -1
  59. data/test/sass/more_templates/more_import.sass +3 -3
  60. data/test/sass/plugin_test.rb +28 -8
  61. data/test/sass/results/compact.css +1 -1
  62. data/test/sass/results/complex.css +5 -5
  63. data/test/sass/results/compressed.css +1 -1
  64. data/test/sass/results/expanded.css +1 -1
  65. data/test/sass/results/import.css +3 -1
  66. data/test/sass/results/mixins.css +12 -12
  67. data/test/sass/results/nested.css +1 -1
  68. data/test/sass/results/parent_ref.css +4 -4
  69. data/test/sass/results/script.css +3 -3
  70. data/test/sass/results/scss_import.css +15 -0
  71. data/test/sass/results/scss_importee.css +2 -0
  72. data/test/sass/script_conversion_test.rb +153 -0
  73. data/test/sass/script_test.rb +44 -54
  74. data/test/sass/scss/css_test.rb +811 -0
  75. data/test/sass/scss/rx_test.rb +156 -0
  76. data/test/sass/scss/scss_test.rb +871 -0
  77. data/test/sass/scss/test_helper.rb +37 -0
  78. data/test/sass/templates/alt.sass +2 -2
  79. data/test/sass/templates/bork1.sass +1 -1
  80. data/test/sass/templates/import.sass +4 -4
  81. data/test/sass/templates/importee.sass +3 -3
  82. data/test/sass/templates/line_numbers.sass +1 -1
  83. data/test/sass/templates/mixins.sass +2 -2
  84. data/test/sass/templates/nested_mixin_bork.sass +1 -1
  85. data/test/sass/templates/options.sass +1 -1
  86. data/test/sass/templates/parent_ref.sass +2 -2
  87. data/test/sass/templates/script.sass +69 -69
  88. data/test/sass/templates/scss_import.scss +10 -0
  89. data/test/sass/templates/scss_importee.scss +1 -0
  90. data/test/sass/templates/units.sass +10 -10
  91. data/test/test_helper.rb +4 -4
  92. 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
- # !color = hsl(120deg, 100%, 50%)
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
@@ -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
- Token = Struct.new(:type, :value, :line, :offset)
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
- :variable => /!([\w-]+)/,
59
- :ident => /(\\.|[^\s\\+*\/%(),=!])+/,
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 => /\##{"([0-9a-fA-F]{1,2})" * 3}|(#{Color::HTML4_COLORS.keys.join("|")})(?![^\s+*\/%),=!])/,
99
+ :color => HEXCOLOR,
62
100
  :bool => /(true|false)\b/,
63
- :op => %r{(#{Regexp.union(*OP_NAMES.map{|s| Regexp.new(Regexp.escape(s) + (s =~ /\w$/ ? '(?:\b|$)' : ''))})})}
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 = token
131
- unless value
132
- raise SyntaxError.new("Syntax error in '#{@scanner.string}' at character #{current_position}.")
133
- end
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
- @scanner.scan(REGULAR_EXPRESSIONS[:whitespace])
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
- return string(@interpolation_stack.pop, true) if after_interpolation?
143
- variable || string(:double, false) || string(:single, false) || number || color || bool || op || ident
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
- return unless @scanner.scan(REGULAR_EXPRESSIONS[:variable])
148
- [:const, @scanner[1]]
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 = @scanner.scan(REGULAR_EXPRESSIONS[:ident])
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 @scanner.scan(STRING_REGULAR_EXPRESSIONS[[re, open]])
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 @scanner.scan(REGULAR_EXPRESSIONS[:number])
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 @scanner.scan(REGULAR_EXPRESSIONS[:color])
171
- value = if @scanner[4]
172
- color = Color::HTML4_COLORS[@scanner[4].downcase]
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 = @scanner.scan(REGULAR_EXPRESSIONS[:bool])
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
- prev_chr = @scanner.string[@scanner.pos - 1].chr
186
- return unless op = @scanner.scan(REGULAR_EXPRESSIONS[:op])
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 current_position
191
- @offset + @scanner.pos + 1
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 last_match_position
195
- current_position - @scanner.matched_size
302
+ def current_position
303
+ @offset + 1
196
304
  end
197
305
 
198
306
  def after_interpolation?
@@ -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
- end
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. `!a !b`, `"foo" "bar"`).
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. `!a, !b`, `"foo", "bar"`).
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 `-` operation (e.g. `-!a`).
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. `/!a`).
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