merbjedi-haml 2.1.0
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.
- data/FAQ +138 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +332 -0
- data/REVISION +1 -0
- data/Rakefile +184 -0
- data/VERSION +1 -0
- data/bin/css2sass +7 -0
- data/bin/haml +9 -0
- data/bin/html2haml +7 -0
- data/bin/sass +8 -0
- data/extra/haml-mode.el +434 -0
- data/extra/sass-mode.el +98 -0
- data/init.rb +8 -0
- data/lib/haml.rb +1025 -0
- data/lib/haml/buffer.rb +255 -0
- data/lib/haml/engine.rb +268 -0
- data/lib/haml/error.rb +22 -0
- data/lib/haml/exec.rb +395 -0
- data/lib/haml/filters.rb +276 -0
- data/lib/haml/helpers.rb +465 -0
- data/lib/haml/helpers/action_view_extensions.rb +45 -0
- data/lib/haml/helpers/action_view_mods.rb +181 -0
- data/lib/haml/html.rb +218 -0
- data/lib/haml/precompiler.rb +896 -0
- data/lib/haml/shared.rb +45 -0
- data/lib/haml/template.rb +51 -0
- data/lib/haml/template/patch.rb +58 -0
- data/lib/haml/template/plugin.rb +72 -0
- data/lib/haml/util.rb +77 -0
- data/lib/haml/version.rb +47 -0
- data/lib/sass.rb +1062 -0
- data/lib/sass/css.rb +388 -0
- data/lib/sass/engine.rb +501 -0
- data/lib/sass/environment.rb +33 -0
- data/lib/sass/error.rb +35 -0
- data/lib/sass/plugin.rb +203 -0
- data/lib/sass/plugin/merb.rb +56 -0
- data/lib/sass/plugin/rails.rb +24 -0
- data/lib/sass/repl.rb +44 -0
- data/lib/sass/script.rb +38 -0
- data/lib/sass/script/bool.rb +13 -0
- data/lib/sass/script/color.rb +97 -0
- data/lib/sass/script/funcall.rb +28 -0
- data/lib/sass/script/functions.rb +122 -0
- data/lib/sass/script/lexer.rb +144 -0
- data/lib/sass/script/literal.rb +60 -0
- data/lib/sass/script/number.rb +231 -0
- data/lib/sass/script/operation.rb +30 -0
- data/lib/sass/script/parser.rb +142 -0
- data/lib/sass/script/string.rb +42 -0
- data/lib/sass/script/unary_operation.rb +21 -0
- data/lib/sass/script/variable.rb +20 -0
- data/lib/sass/tree/attr_node.rb +64 -0
- data/lib/sass/tree/comment_node.rb +30 -0
- data/lib/sass/tree/debug_node.rb +22 -0
- data/lib/sass/tree/directive_node.rb +50 -0
- data/lib/sass/tree/file_node.rb +27 -0
- data/lib/sass/tree/for_node.rb +29 -0
- data/lib/sass/tree/if_node.rb +27 -0
- data/lib/sass/tree/mixin_def_node.rb +18 -0
- data/lib/sass/tree/mixin_node.rb +34 -0
- data/lib/sass/tree/node.rb +97 -0
- data/lib/sass/tree/rule_node.rb +120 -0
- data/lib/sass/tree/variable_node.rb +24 -0
- data/lib/sass/tree/while_node.rb +20 -0
- data/rails/init.rb +1 -0
- data/test/benchmark.rb +99 -0
- data/test/haml/engine_test.rb +852 -0
- data/test/haml/helper_test.rb +224 -0
- data/test/haml/html2haml_test.rb +92 -0
- data/test/haml/markaby/standard.mab +52 -0
- data/test/haml/mocks/article.rb +6 -0
- data/test/haml/results/content_for_layout.xhtml +15 -0
- data/test/haml/results/eval_suppressed.xhtml +9 -0
- data/test/haml/results/filters.xhtml +62 -0
- data/test/haml/results/helpers.xhtml +93 -0
- data/test/haml/results/helpful.xhtml +10 -0
- data/test/haml/results/just_stuff.xhtml +68 -0
- data/test/haml/results/list.xhtml +12 -0
- data/test/haml/results/nuke_inner_whitespace.xhtml +40 -0
- data/test/haml/results/nuke_outer_whitespace.xhtml +148 -0
- data/test/haml/results/original_engine.xhtml +20 -0
- data/test/haml/results/partial_layout.xhtml +5 -0
- data/test/haml/results/partials.xhtml +21 -0
- data/test/haml/results/render_layout.xhtml +3 -0
- data/test/haml/results/silent_script.xhtml +74 -0
- data/test/haml/results/standard.xhtml +42 -0
- data/test/haml/results/tag_parsing.xhtml +23 -0
- data/test/haml/results/very_basic.xhtml +5 -0
- data/test/haml/results/whitespace_handling.xhtml +89 -0
- data/test/haml/rhtml/_av_partial_1.rhtml +12 -0
- data/test/haml/rhtml/_av_partial_2.rhtml +8 -0
- data/test/haml/rhtml/action_view.rhtml +62 -0
- data/test/haml/rhtml/standard.rhtml +54 -0
- data/test/haml/template_test.rb +204 -0
- data/test/haml/templates/_av_partial_1.haml +9 -0
- data/test/haml/templates/_av_partial_1_ugly.haml +9 -0
- data/test/haml/templates/_av_partial_2.haml +5 -0
- data/test/haml/templates/_av_partial_2_ugly.haml +5 -0
- data/test/haml/templates/_layout.erb +3 -0
- data/test/haml/templates/_layout_for_partial.haml +3 -0
- data/test/haml/templates/_partial.haml +8 -0
- data/test/haml/templates/_text_area.haml +3 -0
- data/test/haml/templates/action_view.haml +47 -0
- data/test/haml/templates/action_view_ugly.haml +47 -0
- data/test/haml/templates/breakage.haml +8 -0
- data/test/haml/templates/content_for_layout.haml +10 -0
- data/test/haml/templates/eval_suppressed.haml +11 -0
- data/test/haml/templates/filters.haml +66 -0
- data/test/haml/templates/helpers.haml +95 -0
- data/test/haml/templates/helpful.haml +11 -0
- data/test/haml/templates/just_stuff.haml +83 -0
- data/test/haml/templates/list.haml +12 -0
- data/test/haml/templates/nuke_inner_whitespace.haml +32 -0
- data/test/haml/templates/nuke_outer_whitespace.haml +144 -0
- data/test/haml/templates/original_engine.haml +17 -0
- data/test/haml/templates/partial_layout.haml +3 -0
- data/test/haml/templates/partialize.haml +1 -0
- data/test/haml/templates/partials.haml +12 -0
- data/test/haml/templates/render_layout.haml +2 -0
- data/test/haml/templates/silent_script.haml +40 -0
- data/test/haml/templates/standard.haml +42 -0
- data/test/haml/templates/standard_ugly.haml +42 -0
- data/test/haml/templates/tag_parsing.haml +21 -0
- data/test/haml/templates/very_basic.haml +4 -0
- data/test/haml/templates/whitespace_handling.haml +87 -0
- data/test/linked_rails.rb +12 -0
- data/test/sass/css2sass_test.rb +193 -0
- data/test/sass/engine_test.rb +752 -0
- data/test/sass/functions_test.rb +96 -0
- data/test/sass/more_results/more1.css +9 -0
- data/test/sass/more_results/more1_with_line_comments.css +26 -0
- data/test/sass/more_results/more_import.css +29 -0
- data/test/sass/more_templates/_more_partial.sass +2 -0
- data/test/sass/more_templates/more1.sass +23 -0
- data/test/sass/more_templates/more_import.sass +11 -0
- data/test/sass/plugin_test.rb +208 -0
- data/test/sass/results/alt.css +4 -0
- data/test/sass/results/basic.css +9 -0
- data/test/sass/results/compact.css +5 -0
- data/test/sass/results/complex.css +87 -0
- data/test/sass/results/compressed.css +1 -0
- data/test/sass/results/expanded.css +19 -0
- data/test/sass/results/import.css +29 -0
- data/test/sass/results/line_numbers.css +49 -0
- data/test/sass/results/mixins.css +95 -0
- data/test/sass/results/multiline.css +24 -0
- data/test/sass/results/nested.css +22 -0
- data/test/sass/results/parent_ref.css +13 -0
- data/test/sass/results/script.css +16 -0
- data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
- data/test/sass/results/subdir/subdir.css +3 -0
- data/test/sass/results/units.css +11 -0
- data/test/sass/script_test.rb +152 -0
- data/test/sass/templates/_partial.sass +2 -0
- data/test/sass/templates/alt.sass +16 -0
- data/test/sass/templates/basic.sass +23 -0
- data/test/sass/templates/bork.sass +2 -0
- data/test/sass/templates/bork2.sass +2 -0
- data/test/sass/templates/compact.sass +17 -0
- data/test/sass/templates/complex.sass +309 -0
- data/test/sass/templates/compressed.sass +15 -0
- data/test/sass/templates/expanded.sass +17 -0
- data/test/sass/templates/import.sass +11 -0
- data/test/sass/templates/importee.sass +19 -0
- data/test/sass/templates/line_numbers.sass +13 -0
- data/test/sass/templates/mixins.sass +76 -0
- data/test/sass/templates/multiline.sass +20 -0
- data/test/sass/templates/nested.sass +25 -0
- data/test/sass/templates/parent_ref.sass +25 -0
- data/test/sass/templates/script.sass +101 -0
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
- data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
- data/test/sass/templates/subdir/subdir.sass +6 -0
- data/test/sass/templates/units.sass +11 -0
- data/test/test_helper.rb +21 -0
- metadata +273 -0
@@ -0,0 +1,231 @@
|
|
1
|
+
require 'sass/script/literal'
|
2
|
+
|
3
|
+
module Sass::Script
|
4
|
+
class Number < Literal # :nodoc:
|
5
|
+
|
6
|
+
attr_reader :numerator_units, :denominator_units
|
7
|
+
|
8
|
+
PRECISION = 1000.0
|
9
|
+
|
10
|
+
def initialize(value, numerator_units = [], denominator_units = [])
|
11
|
+
super(value)
|
12
|
+
@numerator_units = numerator_units
|
13
|
+
@denominator_units = denominator_units
|
14
|
+
normalize!
|
15
|
+
end
|
16
|
+
|
17
|
+
def plus(other)
|
18
|
+
if other.is_a? Number
|
19
|
+
operate(other, :+)
|
20
|
+
elsif other.is_a?(Color)
|
21
|
+
other.plus(self)
|
22
|
+
else
|
23
|
+
Sass::Script::String.new(self.to_s + other.to_s)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def minus(other)
|
28
|
+
if other.is_a? Number
|
29
|
+
operate(other, :-)
|
30
|
+
else
|
31
|
+
raise NoMethodError.new(nil, :minus)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def unary_minus
|
36
|
+
Number.new(-value, numerator_units, denominator_units)
|
37
|
+
end
|
38
|
+
|
39
|
+
def times(other)
|
40
|
+
if other.is_a? Number
|
41
|
+
self.operate(other, :*)
|
42
|
+
elsif other.is_a? Color
|
43
|
+
other.times(self)
|
44
|
+
else
|
45
|
+
raise NoMethodError.new(nil, :times)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def div(other)
|
50
|
+
if other.is_a? Number
|
51
|
+
operate(other, :/)
|
52
|
+
else
|
53
|
+
raise NoMethodError.new(nil, :div)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def mod(other)
|
58
|
+
if other.is_a?(Number)
|
59
|
+
unless other.unitless?
|
60
|
+
raise Sass::SyntaxError.new("Cannot modulo by a number with units: #{other.inspect}.")
|
61
|
+
end
|
62
|
+
operate(other, :%)
|
63
|
+
else
|
64
|
+
raise NoMethodError.new(nil, :mod)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def eq(other)
|
69
|
+
Sass::Script::Bool.new(super.to_bool &&
|
70
|
+
self.numerator_units.sort == other.numerator_units.sort &&
|
71
|
+
self.denominator_units.sort == other.denominator_units.sort)
|
72
|
+
end
|
73
|
+
|
74
|
+
def gt(other)
|
75
|
+
raise NoMethodError.new(nil, :gt) unless other.is_a?(Number)
|
76
|
+
operate(other, :>)
|
77
|
+
end
|
78
|
+
|
79
|
+
def gte(other)
|
80
|
+
raise NoMethodError.new(nil, :gt) unless other.is_a?(Number)
|
81
|
+
operate(other, :>=)
|
82
|
+
end
|
83
|
+
|
84
|
+
def lt(other)
|
85
|
+
raise NoMethodError.new(nil, :gt) unless other.is_a?(Number)
|
86
|
+
operate(other, :<)
|
87
|
+
end
|
88
|
+
|
89
|
+
def lte(other)
|
90
|
+
raise NoMethodError.new(nil, :gt) unless other.is_a?(Number)
|
91
|
+
operate(other, :<=)
|
92
|
+
end
|
93
|
+
|
94
|
+
def to_s
|
95
|
+
raise Sass::SyntaxError.new("#{inspect} isn't a valid CSS value.") unless legal_units?
|
96
|
+
inspect
|
97
|
+
end
|
98
|
+
|
99
|
+
def inspect
|
100
|
+
value =
|
101
|
+
if self.value.is_a?(Float) && (self.value.infinite? || self.value.nan?)
|
102
|
+
self.value
|
103
|
+
elsif int?
|
104
|
+
self.value.to_i
|
105
|
+
else
|
106
|
+
(self.value * PRECISION).round / PRECISION
|
107
|
+
end
|
108
|
+
"#{value}#{unit_str}"
|
109
|
+
end
|
110
|
+
|
111
|
+
def to_i
|
112
|
+
super unless int?
|
113
|
+
return value
|
114
|
+
end
|
115
|
+
|
116
|
+
def int?
|
117
|
+
value % 1 == 0.0
|
118
|
+
end
|
119
|
+
|
120
|
+
def unitless?
|
121
|
+
numerator_units.empty? && denominator_units.empty?
|
122
|
+
end
|
123
|
+
|
124
|
+
def legal_units?
|
125
|
+
(numerator_units.empty? || numerator_units.size == 1) && denominator_units.empty?
|
126
|
+
end
|
127
|
+
|
128
|
+
protected
|
129
|
+
|
130
|
+
def operate(other, operation)
|
131
|
+
this = self
|
132
|
+
if [:+, :-].include?(operation)
|
133
|
+
if unitless?
|
134
|
+
this = this.coerce(other.numerator_units, other.denominator_units)
|
135
|
+
else
|
136
|
+
other = other.coerce(numerator_units, denominator_units)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
# avoid integer division
|
140
|
+
value = (:/ == operation) ? this.value.to_f : this.value
|
141
|
+
result = value.send(operation, other.value)
|
142
|
+
|
143
|
+
if result.is_a?(Numeric)
|
144
|
+
Number.new(result, *compute_units(this, other, operation))
|
145
|
+
else # Boolean op
|
146
|
+
Bool.new(result)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def coerce(num_units, den_units)
|
151
|
+
Number.new(if unitless?
|
152
|
+
self.value
|
153
|
+
else
|
154
|
+
self.value * coercion_factor(self.numerator_units, num_units) /
|
155
|
+
coercion_factor(self.denominator_units, den_units)
|
156
|
+
end, num_units, den_units)
|
157
|
+
end
|
158
|
+
|
159
|
+
def coercion_factor(from_units, to_units)
|
160
|
+
# get a list of unmatched units
|
161
|
+
from_units, to_units = sans_common_units(from_units, to_units)
|
162
|
+
|
163
|
+
if from_units.size != to_units.size || !convertable?(from_units | to_units)
|
164
|
+
raise Sass::SyntaxError.new("Incompatible units: '#{from_units.join('*')}' and '#{to_units.join('*')}'.")
|
165
|
+
end
|
166
|
+
|
167
|
+
from_units.zip(to_units).inject(1) {|m,p| m * conversion_factor(p[0], p[1]) }
|
168
|
+
end
|
169
|
+
|
170
|
+
def compute_units(this, other, operation)
|
171
|
+
case operation
|
172
|
+
when :*
|
173
|
+
[this.numerator_units + other.numerator_units, this.denominator_units + other.denominator_units]
|
174
|
+
when :/
|
175
|
+
[this.numerator_units + other.denominator_units, this.denominator_units + other.numerator_units]
|
176
|
+
else
|
177
|
+
[this.numerator_units, this.denominator_units]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def unit_str
|
182
|
+
rv = numerator_units.join("*")
|
183
|
+
if denominator_units.any?
|
184
|
+
rv << "/"
|
185
|
+
rv << denominator_units.join("*")
|
186
|
+
end
|
187
|
+
rv
|
188
|
+
end
|
189
|
+
|
190
|
+
def normalize!
|
191
|
+
return if unitless?
|
192
|
+
@numerator_units, @denominator_units = sans_common_units(numerator_units, denominator_units)
|
193
|
+
|
194
|
+
@denominator_units.each_with_index do |d, i|
|
195
|
+
if convertable?(d) && (u = @numerator_units.detect(&method(:convertable?)))
|
196
|
+
@value /= conversion_factor(d, u)
|
197
|
+
@denominator_units.delete_at(i)
|
198
|
+
@numerator_units.delete_at(@numerator_units.index(u))
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# A hash of unit names to their index in the conversion table
|
204
|
+
CONVERTABLE_UNITS = {"in" => 0, "cm" => 1, "pc" => 2, "mm" => 3, "pt" => 4}
|
205
|
+
CONVERSION_TABLE = [[ 1, 2.54, 6, 25.4, 72 ], # in
|
206
|
+
[ nil, 1, 2.36220473, 10, 28.3464567], # cm
|
207
|
+
[ nil, nil, 1, 4.23333333, 12 ], # pc
|
208
|
+
[ nil, nil, nil, 1, 2.83464567], # mm
|
209
|
+
[ nil, nil, nil, nil, 1 ]] # pt
|
210
|
+
|
211
|
+
def conversion_factor(from_unit, to_unit)
|
212
|
+
res = CONVERSION_TABLE[CONVERTABLE_UNITS[from_unit]][CONVERTABLE_UNITS[to_unit]]
|
213
|
+
return 1.0 / conversion_factor(to_unit, from_unit) if res.nil?
|
214
|
+
res
|
215
|
+
end
|
216
|
+
|
217
|
+
def convertable?(units)
|
218
|
+
Array(units).all?(&CONVERTABLE_UNITS.method(:include?))
|
219
|
+
end
|
220
|
+
|
221
|
+
def sans_common_units(units1, units2)
|
222
|
+
units2 = units2.dup
|
223
|
+
# Can't just use -, because we want px*px to coerce properly to px*mm
|
224
|
+
return units1.map do |u|
|
225
|
+
next u unless j = units2.index(u)
|
226
|
+
units2.delete_at(j)
|
227
|
+
nil
|
228
|
+
end.compact, units2
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'sass/script/string'
|
2
|
+
require 'sass/script/number'
|
3
|
+
require 'sass/script/color'
|
4
|
+
require 'sass/script/functions'
|
5
|
+
require 'sass/script/unary_operation'
|
6
|
+
|
7
|
+
module Sass::Script
|
8
|
+
class Operation # :nodoc:
|
9
|
+
def initialize(operand1, operand2, operator)
|
10
|
+
@operand1 = operand1
|
11
|
+
@operand2 = operand2
|
12
|
+
@operator = operator
|
13
|
+
end
|
14
|
+
|
15
|
+
def inspect
|
16
|
+
"(#{@operator.inspect} #{@operand1.inspect} #{@operand2.inspect})"
|
17
|
+
end
|
18
|
+
|
19
|
+
def perform(environment)
|
20
|
+
literal1 = @operand1.perform(environment)
|
21
|
+
literal2 = @operand2.perform(environment)
|
22
|
+
begin
|
23
|
+
literal1.send(@operator, literal2)
|
24
|
+
rescue NoMethodError => e
|
25
|
+
raise e unless e.name.to_s == @operator.to_s
|
26
|
+
raise Sass::SyntaxError.new("Undefined operation: \"#{literal1} #{@operator} #{literal2}\".")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'sass/script/lexer'
|
2
|
+
|
3
|
+
module Sass
|
4
|
+
module Script
|
5
|
+
class Parser
|
6
|
+
def initialize(str, line, offset, filename = nil)
|
7
|
+
@filename = filename
|
8
|
+
@lexer = Lexer.new(str, line, offset)
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse_interpolated
|
12
|
+
expr = assert_expr :expr
|
13
|
+
assert_tok :right_bracket
|
14
|
+
expr
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse
|
18
|
+
expr = assert_expr :expr
|
19
|
+
raise Sass::SyntaxError.new("Unexpected #{@lexer.peek.type} token.") unless @lexer.done?
|
20
|
+
expr
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.parse(*args)
|
24
|
+
new(*args).parse
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Defines a simple left-associative production.
|
30
|
+
# name is the name of the production,
|
31
|
+
# sub is the name of the production beneath it,
|
32
|
+
# and ops is a list of operators for this precedence level
|
33
|
+
def self.production(name, sub, *ops)
|
34
|
+
class_eval <<RUBY
|
35
|
+
def #{name}
|
36
|
+
return unless e = #{sub}
|
37
|
+
while tok = try_tok(#{ops.map {|o| o.inspect}.join(', ')})
|
38
|
+
e = Operation.new(e, assert_expr(#{sub.inspect}), tok.type)
|
39
|
+
end
|
40
|
+
e
|
41
|
+
end
|
42
|
+
RUBY
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.unary(op, sub)
|
46
|
+
class_eval <<RUBY
|
47
|
+
def unary_#{op}
|
48
|
+
return #{sub} unless try_tok(:#{op})
|
49
|
+
UnaryOperation.new(assert_expr(:unary_#{op}), :#{op})
|
50
|
+
end
|
51
|
+
RUBY
|
52
|
+
end
|
53
|
+
|
54
|
+
production :expr, :concat, :comma
|
55
|
+
|
56
|
+
def concat
|
57
|
+
return unless e = or_expr
|
58
|
+
while sub = or_expr
|
59
|
+
e = Operation.new(e, sub, :concat)
|
60
|
+
end
|
61
|
+
e
|
62
|
+
end
|
63
|
+
|
64
|
+
production :or_expr, :and_expr, :or
|
65
|
+
production :and_expr, :eq_or_neq, :and
|
66
|
+
production :eq_or_neq, :relational, :eq, :neq
|
67
|
+
production :relational, :plus_or_minus, :gt, :gte, :lt, :lte
|
68
|
+
production :plus_or_minus, :times_div_or_mod, :plus, :minus
|
69
|
+
production :times_div_or_mod, :unary_minus, :times, :div, :mod
|
70
|
+
|
71
|
+
unary :minus, :unary_div
|
72
|
+
unary :div, :unary_not # For strings, so /foo/bar works
|
73
|
+
unary :not, :funcall
|
74
|
+
|
75
|
+
def funcall
|
76
|
+
return paren unless name = try_tok(:ident)
|
77
|
+
# An identifier without arguments is just a string
|
78
|
+
unless try_tok(:lparen)
|
79
|
+
warn(<<END)
|
80
|
+
DEPRECATION WARNING:
|
81
|
+
On line #{name.line}, character #{name.offset}#{" of '#{@filename}'" if @filename}
|
82
|
+
Implicit strings have been deprecated and will be removed in version 2.4.
|
83
|
+
'#{name.value}' was not quoted. Please add double quotes (e.g. "#{name.value}").
|
84
|
+
END
|
85
|
+
Script::String.new(name.value)
|
86
|
+
else
|
87
|
+
args = arglist || []
|
88
|
+
assert_tok(:rparen)
|
89
|
+
Script::Funcall.new(name.value, args)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def arglist
|
94
|
+
return unless e = concat
|
95
|
+
return [e] unless try_tok(:comma)
|
96
|
+
[e, *arglist]
|
97
|
+
end
|
98
|
+
|
99
|
+
def paren
|
100
|
+
return variable unless try_tok(:lparen)
|
101
|
+
e = assert_expr(:expr)
|
102
|
+
assert_tok(:rparen)
|
103
|
+
return e
|
104
|
+
end
|
105
|
+
|
106
|
+
def variable
|
107
|
+
return string unless c = try_tok(:const)
|
108
|
+
Variable.new(c.value)
|
109
|
+
end
|
110
|
+
|
111
|
+
def string
|
112
|
+
return literal unless first = try_tok(:string)
|
113
|
+
return first.value unless try_tok(:begin_interpolation)
|
114
|
+
mid = parse_interpolated
|
115
|
+
last = assert_tok(:string)
|
116
|
+
Operation.new(first.value, Operation.new(mid, last.value, :plus), :plus)
|
117
|
+
end
|
118
|
+
|
119
|
+
def literal
|
120
|
+
(t = try_tok(:number, :color, :bool)) && (return t.value)
|
121
|
+
end
|
122
|
+
|
123
|
+
# It would be possible to have unified #assert and #try methods,
|
124
|
+
# but detecting the method/token difference turns out to be quite expensive.
|
125
|
+
|
126
|
+
def assert_expr(name)
|
127
|
+
(e = send(name)) && (return e)
|
128
|
+
raise Sass::SyntaxError.new("Expected expression, was #{@lexer.done? ? 'end of text' : "#{@lexer.peek.type} token"}.")
|
129
|
+
end
|
130
|
+
|
131
|
+
def assert_tok(*names)
|
132
|
+
(t = try_tok(*names)) && (return t)
|
133
|
+
raise Sass::SyntaxError.new("Expected #{names.join(' or ')} token, was #{@lexer.done? ? 'end of text' : "#{@lexer.peek.type} token"}.")
|
134
|
+
end
|
135
|
+
|
136
|
+
def try_tok(*names)
|
137
|
+
peeked = @lexer.peek
|
138
|
+
peeked && names.include?(peeked.type) && @lexer.token
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'sass/script/literal'
|
2
|
+
|
3
|
+
module Sass::Script
|
4
|
+
class String < Literal # :nodoc:
|
5
|
+
INTERPOLATION = /(^|[^\\])\#\{([^}]*)\}/
|
6
|
+
#TODO pass line & char context to perform
|
7
|
+
def perform(environment)
|
8
|
+
interpolated = @value.gsub(INTERPOLATION) do |match|
|
9
|
+
"#{$1}#{Sass::Script.resolve($2, 0, 0, environment)}"
|
10
|
+
end
|
11
|
+
Sass::Script::String.new(interpolated)
|
12
|
+
end
|
13
|
+
|
14
|
+
def plus(other)
|
15
|
+
Sass::Script::String.new(self.to_s + other.to_s)
|
16
|
+
end
|
17
|
+
|
18
|
+
def minus(other)
|
19
|
+
Sass::Script::String.new("#{self.to_s}-#{other.to_s}")
|
20
|
+
end
|
21
|
+
|
22
|
+
def unary_minus
|
23
|
+
Sass::Script::String.new("-#{self.to_s}")
|
24
|
+
end
|
25
|
+
|
26
|
+
def div(other)
|
27
|
+
Sass::Script::String.new("#{self.to_s}/#{other.to_s}")
|
28
|
+
end
|
29
|
+
|
30
|
+
def unary_div
|
31
|
+
Sass::Script::String.new("/#{self.to_s}")
|
32
|
+
end
|
33
|
+
|
34
|
+
def funcall(other)
|
35
|
+
Sass::Script::String.new("#{self.to_s}(#{other.to_s})")
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
@value
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Sass::Script
|
2
|
+
class UnaryOperation # :nodoc:
|
3
|
+
def initialize(operand, operator)
|
4
|
+
@operand = operand
|
5
|
+
@operator = operator
|
6
|
+
end
|
7
|
+
|
8
|
+
def inspect
|
9
|
+
"(#{@operator.inspect} #{@operand.inspect})"
|
10
|
+
end
|
11
|
+
|
12
|
+
def perform(environment)
|
13
|
+
operator = "unary_#{@operator}"
|
14
|
+
literal = @operand.perform(environment)
|
15
|
+
literal.send(operator)
|
16
|
+
rescue NoMethodError => e
|
17
|
+
raise e unless e.name.to_s == operator.to_s
|
18
|
+
raise Sass::SyntaxError.new("Undefined unary operation: \"#{@operator} #{literal}\".")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|