haml 2.2.24 → 3.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of haml might be problematic. Click here for more details.
- data/.yardopts +0 -1
- data/README.md +91 -151
- data/REMEMBER +11 -1
- data/Rakefile +73 -55
- data/VERSION +1 -1
- data/VERSION_NAME +1 -1
- data/bin/css2sass +7 -1
- data/bin/sass-convert +7 -0
- data/extra/haml-mode.el +2 -1
- data/lib/haml/buffer.rb +22 -4
- data/lib/haml/engine.rb +5 -1
- data/lib/haml/exec.rb +231 -46
- data/lib/haml/filters.rb +19 -8
- data/lib/haml/helpers.rb +47 -20
- data/lib/haml/helpers/action_view_extensions.rb +2 -4
- data/lib/haml/helpers/action_view_mods.rb +11 -8
- data/lib/haml/helpers/xss_mods.rb +13 -2
- data/lib/haml/html.rb +179 -48
- data/lib/haml/html/erb.rb +141 -0
- data/lib/haml/precompiler.rb +40 -15
- data/lib/haml/railtie.rb +1 -5
- data/lib/haml/root.rb +3 -0
- data/lib/haml/template.rb +4 -14
- data/lib/haml/util.rb +120 -30
- data/lib/haml/version.rb +25 -2
- data/lib/sass.rb +5 -1
- data/lib/sass/callbacks.rb +50 -0
- data/lib/sass/css.rb +40 -191
- data/lib/sass/engine.rb +170 -74
- data/lib/sass/environment.rb +8 -2
- data/lib/sass/error.rb +163 -25
- data/lib/sass/files.rb +31 -28
- data/lib/sass/plugin.rb +268 -87
- data/lib/sass/plugin/rails.rb +9 -4
- data/lib/sass/repl.rb +1 -1
- data/lib/sass/script.rb +31 -29
- data/lib/sass/script/bool.rb +1 -0
- data/lib/sass/script/color.rb +290 -23
- data/lib/sass/script/css_lexer.rb +22 -0
- data/lib/sass/script/css_parser.rb +28 -0
- data/lib/sass/script/funcall.rb +22 -3
- data/lib/sass/script/functions.rb +523 -33
- data/lib/sass/script/interpolation.rb +42 -0
- data/lib/sass/script/lexer.rb +169 -52
- data/lib/sass/script/literal.rb +58 -9
- data/lib/sass/script/node.rb +79 -1
- data/lib/sass/script/number.rb +20 -5
- data/lib/sass/script/operation.rb +49 -3
- data/lib/sass/script/parser.rb +162 -28
- data/lib/sass/script/string.rb +50 -2
- data/lib/sass/script/unary_operation.rb +25 -2
- data/lib/sass/script/variable.rb +21 -4
- 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 +69 -27
- data/lib/sass/tree/debug_node.rb +7 -2
- data/lib/sass/tree/directive_node.rb +41 -35
- data/lib/sass/tree/for_node.rb +6 -0
- data/lib/sass/tree/if_node.rb +13 -1
- data/lib/sass/tree/import_node.rb +52 -27
- data/lib/sass/tree/mixin_def_node.rb +18 -0
- data/lib/sass/tree/mixin_node.rb +41 -6
- data/lib/sass/tree/node.rb +197 -70
- data/lib/sass/tree/prop_node.rb +152 -57
- data/lib/sass/tree/root_node.rb +118 -0
- data/lib/sass/tree/rule_node.rb +193 -96
- data/lib/sass/tree/variable_node.rb +9 -5
- data/lib/sass/tree/while_node.rb +4 -0
- data/test/benchmark.rb +5 -5
- data/test/haml/engine_test.rb +147 -10
- data/test/haml/{rhtml/_av_partial_1.rhtml → erb/_av_partial_1.erb} +1 -1
- data/test/haml/{rhtml/_av_partial_2.rhtml → erb/_av_partial_2.erb} +1 -1
- data/test/haml/{rhtml/action_view.rhtml → erb/action_view.erb} +1 -1
- data/test/haml/{rhtml/standard.rhtml → erb/standard.erb} +0 -0
- data/test/haml/helper_test.rb +91 -24
- data/test/haml/html2haml/erb_tests.rb +410 -0
- data/test/haml/html2haml_test.rb +210 -66
- data/test/haml/results/filters.xhtml +1 -1
- data/test/haml/results/just_stuff.xhtml +2 -0
- data/test/haml/spec_test.rb +44 -0
- data/test/haml/template_test.rb +22 -2
- data/test/haml/templates/helpers.haml +0 -13
- data/test/haml/templates/just_stuff.haml +2 -0
- data/test/haml/util_test.rb +48 -0
- data/test/sass/callbacks_test.rb +61 -0
- data/test/sass/conversion_test.rb +884 -0
- data/test/sass/css2sass_test.rb +99 -18
- data/test/sass/data/hsl-rgb.txt +319 -0
- data/test/sass/engine_test.rb +1049 -131
- data/test/sass/functions_test.rb +398 -47
- 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 +184 -10
- 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/options.css +1 -0
- 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 +137 -70
- 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 +2 -0
- data/test/sass/templates/bork3.sass +2 -0
- data/test/sass/templates/bork4.sass +2 -0
- 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/mixin_bork.sass +5 -0
- data/test/sass/templates/mixins.sass +2 -2
- 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_mixin_bork.sass +6 -0
- data/test/sass/templates/options.sass +2 -0
- 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 +20 -8
- data/vendor/fssm/LICENSE +20 -0
- data/vendor/fssm/README.markdown +55 -0
- data/vendor/fssm/Rakefile +59 -0
- data/vendor/fssm/VERSION.yml +5 -0
- data/vendor/fssm/example.rb +9 -0
- data/vendor/fssm/fssm.gemspec +77 -0
- data/vendor/fssm/lib/fssm.rb +33 -0
- data/vendor/fssm/lib/fssm/backends/fsevents.rb +36 -0
- data/vendor/fssm/lib/fssm/backends/inotify.rb +26 -0
- data/vendor/fssm/lib/fssm/backends/polling.rb +25 -0
- data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +131 -0
- data/vendor/fssm/lib/fssm/monitor.rb +26 -0
- data/vendor/fssm/lib/fssm/path.rb +91 -0
- data/vendor/fssm/lib/fssm/pathname.rb +502 -0
- data/vendor/fssm/lib/fssm/state/directory.rb +57 -0
- data/vendor/fssm/lib/fssm/state/file.rb +24 -0
- data/vendor/fssm/lib/fssm/support.rb +63 -0
- data/vendor/fssm/lib/fssm/tree.rb +176 -0
- data/vendor/fssm/profile/prof-cache.rb +40 -0
- data/vendor/fssm/profile/prof-fssm-pathname.html +1231 -0
- data/vendor/fssm/profile/prof-pathname.rb +68 -0
- data/vendor/fssm/profile/prof-plain-pathname.html +988 -0
- data/vendor/fssm/profile/prof.html +2379 -0
- data/vendor/fssm/spec/path_spec.rb +75 -0
- data/vendor/fssm/spec/root/duck/quack.txt +0 -0
- data/vendor/fssm/spec/root/file.css +0 -0
- data/vendor/fssm/spec/root/file.rb +0 -0
- data/vendor/fssm/spec/root/file.yml +0 -0
- data/vendor/fssm/spec/root/moo/cow.txt +0 -0
- data/vendor/fssm/spec/spec_helper.rb +14 -0
- metadata +94 -14
- data/test/sass/templates/bork.sass +0 -2
@@ -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,24 +63,63 @@ 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
|
-
:
|
60
|
-
:
|
93
|
+
:whitespace => /\s+/,
|
94
|
+
:comment => COMMENT,
|
95
|
+
:single_line_comment => SINGLE_LINE_COMMENT,
|
96
|
+
:variable => /([!\$])(#{IDENT})/,
|
97
|
+
:ident => IDENT,
|
61
98
|
:number => /(-)?(?:(\d*\.\d+)|(\d+))([a-zA-Z%]+)?/,
|
62
|
-
:color =>
|
99
|
+
:color => HEXCOLOR,
|
63
100
|
:bool => /(true|false)\b/,
|
64
|
-
:
|
101
|
+
:ident_op => %r{(#{Regexp.union(*IDENT_OP_NAMES.map{|s| Regexp.new(Regexp.escape(s) + '(?:\b|$)')})})},
|
102
|
+
:op => %r{(#{Regexp.union(*OP_NAMES)})},
|
103
|
+
}
|
104
|
+
|
105
|
+
class << self
|
106
|
+
private
|
107
|
+
def string_re(open, close)
|
108
|
+
/#{open}((?:\\.|\#(?!\{)|[^#{close}\\#])*)(#{close}|(?=#\{))/
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# A hash of regular expressions that are used for tokenizing strings.
|
113
|
+
#
|
114
|
+
# The key is a [Symbol, Boolean] pair.
|
115
|
+
# The symbol represents which style of quotation to use,
|
116
|
+
# while the boolean represents whether or not the string
|
117
|
+
# is following an interpolated segment.
|
118
|
+
STRING_REGULAR_EXPRESSIONS = {
|
119
|
+
[:double, false] => string_re('"', '"'),
|
120
|
+
[:single, false] => string_re("'", "'"),
|
121
|
+
[:double, true] => string_re('', '"'),
|
122
|
+
[:single, true] => string_re('', "'"),
|
65
123
|
}
|
66
124
|
|
67
125
|
# @param str [String, StringScanner] The source text to lex
|
@@ -69,11 +127,14 @@ module Sass
|
|
69
127
|
# Used for error reporting
|
70
128
|
# @param offset [Fixnum] The number of characters in on which the SassScript appears.
|
71
129
|
# Used for error reporting
|
72
|
-
|
130
|
+
# @param options [{Symbol => Object}] An options hash;
|
131
|
+
# see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
|
132
|
+
def initialize(str, line, offset, options)
|
73
133
|
@scanner = str.is_a?(StringScanner) ? str : StringScanner.new(str)
|
74
134
|
@line = line
|
75
135
|
@offset = offset
|
76
|
-
@
|
136
|
+
@options = options
|
137
|
+
@interpolation_stack = []
|
77
138
|
@prev = nil
|
78
139
|
end
|
79
140
|
|
@@ -87,6 +148,18 @@ module Sass
|
|
87
148
|
return tok
|
88
149
|
end
|
89
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
|
+
|
90
163
|
# Returns the next token without moving the lexer forward.
|
91
164
|
#
|
92
165
|
# @return [Token] The next token
|
@@ -94,96 +167,140 @@ module Sass
|
|
94
167
|
@tok ||= read_token
|
95
168
|
end
|
96
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
|
+
|
97
176
|
# @return [Boolean] Whether or not there's more source text to lex.
|
98
177
|
def done?
|
99
|
-
whitespace unless after_interpolation?
|
178
|
+
whitespace unless after_interpolation? && @interpolation_stack.last
|
100
179
|
@scanner.eos? && @tok.nil?
|
101
180
|
end
|
102
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
|
+
|
103
194
|
private
|
104
195
|
|
105
196
|
def read_token
|
106
197
|
return if done?
|
198
|
+
return unless value = token
|
107
199
|
|
108
|
-
value =
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
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)
|
113
204
|
end
|
114
205
|
|
115
206
|
def whitespace
|
116
|
-
|
207
|
+
nil while scan(REGULAR_EXPRESSIONS[:whitespace]) ||
|
208
|
+
scan(REGULAR_EXPRESSIONS[:comment]) ||
|
209
|
+
scan(REGULAR_EXPRESSIONS[:single_line_comment])
|
117
210
|
end
|
118
211
|
|
119
212
|
def token
|
120
|
-
|
121
|
-
|
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
|
122
220
|
end
|
123
221
|
|
124
222
|
def variable
|
125
|
-
|
126
|
-
[:const, @scanner[1]]
|
223
|
+
_variable(REGULAR_EXPRESSIONS[:variable])
|
127
224
|
end
|
128
225
|
|
129
|
-
def
|
130
|
-
|
131
|
-
|
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]]
|
132
235
|
end
|
133
236
|
|
134
|
-
def
|
135
|
-
return unless
|
136
|
-
[:
|
237
|
+
def ident
|
238
|
+
return unless s = scan(REGULAR_EXPRESSIONS[:ident])
|
239
|
+
[:ident, s.gsub(/\\(.)/, '\1')]
|
137
240
|
end
|
138
241
|
|
139
|
-
def
|
140
|
-
|
242
|
+
def string(re, open)
|
243
|
+
return unless scan(STRING_REGULAR_EXPRESSIONS[[re, open]])
|
244
|
+
@interpolation_stack << re if @scanner[2].empty? # Started an interpolated section
|
245
|
+
[:string, Script::String.new(@scanner[1].gsub(/\\([^0-9a-f])/, '\1').gsub(/\\([0-9a-f]{1,4})/, "\\\\\\1"), :string)]
|
141
246
|
end
|
142
247
|
|
143
248
|
def number
|
144
|
-
return unless
|
249
|
+
return unless scan(REGULAR_EXPRESSIONS[:number])
|
145
250
|
value = @scanner[2] ? @scanner[2].to_f : @scanner[3].to_i
|
146
251
|
value = -value if @scanner[1]
|
147
252
|
[:number, Script::Number.new(value, Array(@scanner[4]))]
|
148
253
|
end
|
149
254
|
|
150
255
|
def color
|
151
|
-
return unless
|
152
|
-
value =
|
153
|
-
|
154
|
-
else
|
155
|
-
(1..3).map {|i| @scanner[i]}.map {|num| num.ljust(2, num).to_i(16)}
|
156
|
-
end
|
256
|
+
return unless s = scan(REGULAR_EXPRESSIONS[:color])
|
257
|
+
value = s.scan(/^#(..?)(..?)(..?)$/).first.
|
258
|
+
map {|num| num.ljust(2, num).to_i(16)}
|
157
259
|
[:color, Script::Color.new(value)]
|
158
260
|
end
|
159
261
|
|
160
262
|
def bool
|
161
|
-
return unless s =
|
263
|
+
return unless s = scan(REGULAR_EXPRESSIONS[:bool])
|
162
264
|
[:bool, Script::Bool.new(s == 'true')]
|
163
265
|
end
|
164
266
|
|
165
|
-
def
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
END
|
176
|
-
end
|
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
|
177
277
|
|
278
|
+
def ident_op
|
279
|
+
return unless op = scan(REGULAR_EXPRESSIONS[:ident_op])
|
178
280
|
[OPERATORS[op]]
|
179
281
|
end
|
180
282
|
|
181
|
-
def
|
182
|
-
|
283
|
+
def op
|
284
|
+
return unless op = scan(REGULAR_EXPRESSIONS[:op])
|
285
|
+
@interpolation_stack << nil if op == :begin_interpolation
|
286
|
+
[OPERATORS[op]]
|
287
|
+
end
|
288
|
+
|
289
|
+
def raw(rx)
|
290
|
+
return unless val = scan(rx)
|
291
|
+
[:raw, val]
|
183
292
|
end
|
184
293
|
|
185
|
-
def
|
186
|
-
|
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
|
300
|
+
end
|
301
|
+
|
302
|
+
def current_position
|
303
|
+
@offset + 1
|
187
304
|
end
|
188
305
|
|
189
306
|
def after_interpolation?
|
data/lib/sass/script/literal.rb
CHANGED
@@ -21,14 +21,32 @@ module Sass::Script
|
|
21
21
|
# @param value [Object] The object for \{#value}
|
22
22
|
def initialize(value = nil)
|
23
23
|
@value = value
|
24
|
+
super()
|
24
25
|
end
|
25
26
|
|
26
|
-
#
|
27
|
+
# Returns an empty array.
|
27
28
|
#
|
28
|
-
# @
|
29
|
-
# @
|
30
|
-
def
|
31
|
-
|
29
|
+
# @return [Array<Node>] empty
|
30
|
+
# @see Node#children
|
31
|
+
def children
|
32
|
+
[]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the options hash for this node.
|
36
|
+
#
|
37
|
+
# @return [{Symbol => Object}]
|
38
|
+
# @raise [Sass::SyntaxError] if the options hash hasn't been set.
|
39
|
+
# This should only happen when the literal was created
|
40
|
+
# outside of the parser and \{#to\_s} was called on it
|
41
|
+
def options
|
42
|
+
opts = super
|
43
|
+
return opts if opts
|
44
|
+
raise Sass::SyntaxError.new(<<MSG)
|
45
|
+
The #options attribute is not set on this #{self.class}.
|
46
|
+
This error is probably occurring because #to_s was called
|
47
|
+
on this literal within a custom Sass function without first
|
48
|
+
setting the #option attribute.
|
49
|
+
MSG
|
32
50
|
end
|
33
51
|
|
34
52
|
# The SassScript `and` operation.
|
@@ -84,7 +102,7 @@ module Sass::Script
|
|
84
102
|
Sass::Script::Bool.new(!to_bool)
|
85
103
|
end
|
86
104
|
|
87
|
-
# The SassScript default operation (e.g.
|
105
|
+
# The SassScript default operation (e.g. `$a $b`, `"foo" "bar"`).
|
88
106
|
#
|
89
107
|
# @param other [Literal] The right-hand side of the operator
|
90
108
|
# @return [Script::String] A string containing both literals
|
@@ -93,7 +111,7 @@ module Sass::Script
|
|
93
111
|
Sass::Script::String.new("#{self.to_s} #{other.to_s}")
|
94
112
|
end
|
95
113
|
|
96
|
-
# The SassScript `,` operation (e.g.
|
114
|
+
# The SassScript `,` operation (e.g. `$a, $b`, `"foo", "bar"`).
|
97
115
|
#
|
98
116
|
# @param other [Literal] The right-hand side of the operator
|
99
117
|
# @return [Script::String] A string containing both literals
|
@@ -108,6 +126,9 @@ module Sass::Script
|
|
108
126
|
# @return [Script::String] A string containing both literals
|
109
127
|
# without any separation
|
110
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
|
111
132
|
Sass::Script::String.new(self.to_s + other.to_s)
|
112
133
|
end
|
113
134
|
|
@@ -129,7 +150,16 @@ module Sass::Script
|
|
129
150
|
Sass::Script::String.new("#{self.to_s}/#{other.to_s}")
|
130
151
|
end
|
131
152
|
|
132
|
-
# 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`).
|
133
163
|
#
|
134
164
|
# @param other [Literal] The right-hand side of the operator
|
135
165
|
# @return [Script::String] A string containing the literal
|
@@ -138,7 +168,7 @@ module Sass::Script
|
|
138
168
|
Sass::Script::String.new("-#{self.to_s}")
|
139
169
|
end
|
140
170
|
|
141
|
-
# The SassScript unary `/` operation (e.g.
|
171
|
+
# The SassScript unary `/` operation (e.g. `/$a`).
|
142
172
|
#
|
143
173
|
# @param other [Literal] The right-hand side of the operator
|
144
174
|
# @return [Script::String] A string containing the literal
|
@@ -173,5 +203,24 @@ module Sass::Script
|
|
173
203
|
|
174
204
|
# @raise [Sass::SyntaxError] if this literal isn't an integer
|
175
205
|
def assert_int!; to_i; end
|
206
|
+
|
207
|
+
# Returns the string representation of this literal
|
208
|
+
# as it would be output to the CSS document.
|
209
|
+
#
|
210
|
+
# @return [String]
|
211
|
+
def to_s
|
212
|
+
raise Sass::SyntaxError.new("[BUG] All subclasses of Sass::Literal must implement #to_s.")
|
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
|
176
225
|
end
|
177
226
|
end
|