haml-edge 2.3.240 → 2.3.241
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/EDGE_GEM_VERSION +1 -1
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/haml/exec.rb +36 -12
- data/lib/sass/less.rb +363 -0
- data/test/sass/less_conversion_test.rb +625 -0
- data/test/sass/templates/importee.less +2 -0
- metadata +6 -2
data/EDGE_GEM_VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.3.
|
1
|
+
2.3.241
|
data/Rakefile
CHANGED
@@ -269,6 +269,7 @@ OPTS
|
|
269
269
|
list.exclude('lib/haml/helpers/xss_mods.rb')
|
270
270
|
list.exclude('lib/sass/plugin/merb.rb')
|
271
271
|
list.exclude('lib/sass/plugin/rails.rb')
|
272
|
+
list.exclude('lib/sass/less.rb')
|
272
273
|
end.to_a
|
273
274
|
t.options << '--incremental' if Rake.application.top_level_tasks.include?('redoc')
|
274
275
|
t.options += FileList.new(scope('yard/*.rb')).to_a.map {|f| ['-e', f]}.flatten
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.3.
|
1
|
+
2.3.241
|
data/lib/haml/exec.rb
CHANGED
@@ -155,6 +155,17 @@ module Haml
|
|
155
155
|
flag = 'wb' if @options[:unix_newlines] && flag == 'w'
|
156
156
|
File.open(filename, flag)
|
157
157
|
end
|
158
|
+
|
159
|
+
def handle_load_error(err)
|
160
|
+
dep = err.message.scan(/^no such file to load -- (.*)/)[0]
|
161
|
+
raise err if @options[:trace] || dep.nil? || dep.empty?
|
162
|
+
$stderr.puts <<MESSAGE
|
163
|
+
Required dependency #{dep} not found!
|
164
|
+
Run "gem install #{dep}" to get it.
|
165
|
+
Use --trace for backtrace.
|
166
|
+
MESSAGE
|
167
|
+
exit 1
|
168
|
+
end
|
158
169
|
end
|
159
170
|
|
160
171
|
# An abstrac class that encapsulates the code
|
@@ -558,14 +569,7 @@ END
|
|
558
569
|
raise "#{e.is_a?(::Haml::SyntaxError) ? "Syntax error" : "Error"} on line " +
|
559
570
|
"#{get_line e}: #{e.message}"
|
560
571
|
rescue LoadError => err
|
561
|
-
|
562
|
-
raise err if @options[:trace] || dep.nil? || dep.empty?
|
563
|
-
$stderr.puts <<MESSAGE
|
564
|
-
Required dependency #{dep} not found!
|
565
|
-
Run "gem install #{dep}" to get it.
|
566
|
-
Use --trace for backtrace.
|
567
|
-
MESSAGE
|
568
|
-
exit 1
|
572
|
+
handle_load_error(err)
|
569
573
|
end
|
570
574
|
end
|
571
575
|
|
@@ -595,14 +599,15 @@ Options:
|
|
595
599
|
END
|
596
600
|
|
597
601
|
opts.on('-F', '--from FORMAT',
|
598
|
-
'The format to convert from. Can be css, scss, sass, or sass2.',
|
602
|
+
'The format to convert from. Can be css, scss, sass, less, or sass2.',
|
599
603
|
'sass2 is the same as sass, but updates more old syntax to new.',
|
600
604
|
'By default, this is inferred from the input filename.',
|
601
605
|
'If there is none, defaults to css.') do |name|
|
602
606
|
@options[:from] = name.downcase.to_sym
|
603
|
-
unless [:css, :scss, :sass, :sass2].include?(@options[:from])
|
607
|
+
unless [:css, :scss, :sass, :less, :sass2].include?(@options[:from])
|
604
608
|
raise "Unknown format for sass-convert --from: #{name}"
|
605
609
|
end
|
610
|
+
try_less_note if @options[:from] == :less
|
606
611
|
end
|
607
612
|
|
608
613
|
opts.on('-T', '--to FORMAT',
|
@@ -685,11 +690,11 @@ END
|
|
685
690
|
if @options[:in_place]
|
686
691
|
f
|
687
692
|
elsif @options[:output]
|
688
|
-
output_name = f.gsub(/\.(c|sa|sc)ss$/, ".#{@options[:to]}")
|
693
|
+
output_name = f.gsub(/\.(c|sa|sc|le)ss$/, ".#{@options[:to]}")
|
689
694
|
output_name[0...@options[:input].size] = @options[:output]
|
690
695
|
output_name
|
691
696
|
else
|
692
|
-
f.gsub(/\.(c|sa|sc)ss$/, ".#{@options[:to]}")
|
697
|
+
f.gsub(/\.(c|sa|sc|le)ss$/, ".#{@options[:to]}")
|
693
698
|
end
|
694
699
|
|
695
700
|
unless File.directory?(File.dirname(output))
|
@@ -715,6 +720,7 @@ END
|
|
715
720
|
case input.path
|
716
721
|
when /\.scss$/; :scss
|
717
722
|
when /\.sass$/; :sass
|
723
|
+
when /\.less$/; :less
|
718
724
|
when /\.css$/; :css
|
719
725
|
end
|
720
726
|
elsif @options[:in_place]
|
@@ -743,6 +749,11 @@ END
|
|
743
749
|
if @options[:from] == :css
|
744
750
|
require 'sass/css'
|
745
751
|
::Sass::CSS.new(input.read, @options[:for_tree]).render(@options[:to])
|
752
|
+
elsif @options[:from] == :less
|
753
|
+
require 'sass/less'
|
754
|
+
try_less_note
|
755
|
+
input = input.read if input.is_a?(IO) && !input.is_a?(File) # Less is dumb
|
756
|
+
Less::Engine.new(input).to_tree.to_sass_tree.send("to_#{@options[:to]}", @options[:for_tree])
|
746
757
|
else
|
747
758
|
if input.is_a?(File)
|
748
759
|
::Sass::Files.tree_for(input.path, @options[:for_engine])
|
@@ -758,6 +769,19 @@ END
|
|
758
769
|
raise e if @options[:trace]
|
759
770
|
file = " of #{e.sass_filename}" if e.sass_filename
|
760
771
|
raise "Error on line #{e.sass_line}#{file}: #{e.message}\n Use --trace for backtrace"
|
772
|
+
rescue LoadError => err
|
773
|
+
handle_load_error(err)
|
774
|
+
end
|
775
|
+
|
776
|
+
@@less_note_printed = false
|
777
|
+
def try_less_note
|
778
|
+
return if @@less_note_printed
|
779
|
+
@@less_note_printed = true
|
780
|
+
warn <<NOTE
|
781
|
+
* NOTE: Sass and Less are different languages, and they work differently.
|
782
|
+
* I'll do my best to translate, but some features -- especially mixins --
|
783
|
+
* should be checked by hand.
|
784
|
+
NOTE
|
761
785
|
end
|
762
786
|
end
|
763
787
|
end
|
data/lib/sass/less.rb
ADDED
@@ -0,0 +1,363 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'less'
|
4
|
+
|
5
|
+
module Less
|
6
|
+
# This is the class that Treetop defines for parsing Less files.
|
7
|
+
# Since not everything gets parsed into the AST but is instead resolved at parse-time,
|
8
|
+
# we need to override some of it so that it can be converted into Sass.
|
9
|
+
module StyleSheet
|
10
|
+
# Selector mixins that don't have arguments.
|
11
|
+
# This depends only on the syntax at the call site;
|
12
|
+
# if it doesn't use parens, it hits this production,
|
13
|
+
# regardless of whether the mixin being called has arguments or not.
|
14
|
+
module Mixin4
|
15
|
+
def build_with_sass(env)
|
16
|
+
selectors.build(env, :mixin).each do |path|
|
17
|
+
el = path.inject(env.root) do |current, node|
|
18
|
+
current.descend(node.selector, node) or raise MixinNameError, "#{selectors.text_value} in #{env}"
|
19
|
+
end
|
20
|
+
if el.is_a?(Node::Mixin::Def)
|
21
|
+
# Calling a mixin with arguments, which gets compiled to a Sass mixin
|
22
|
+
env << Node::Mixin::Call.new(el, [], env)
|
23
|
+
else
|
24
|
+
# Calling a mixin without arguments, which gets compiled to @extend
|
25
|
+
sel = selector_str(path)
|
26
|
+
base = selector_str(selector_base(path))
|
27
|
+
if base == sel
|
28
|
+
env << Node::SassNode.new(Sass::Tree::ExtendNode.new([sel]))
|
29
|
+
else
|
30
|
+
Haml::Util.haml_warn <<WARNING
|
31
|
+
WARNING: Sass doesn't support mixing in selector sequences.
|
32
|
+
Replacing "#{sel}" with "@extend #{base}"
|
33
|
+
WARNING
|
34
|
+
env << Node::SassNode.new(Sass::Tree::CommentNode.new("// #{sel};", true))
|
35
|
+
env << Node::SassNode.new(Sass::Tree::ExtendNode.new([base]))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
alias_method :build_without_sass, :build
|
41
|
+
alias_method :build, :build_with_sass
|
42
|
+
|
43
|
+
def selector_base(path)
|
44
|
+
el, i = Haml::Util.enum_with_index(path).to_a.reverse.find {|e, i| e.selector !~ /^:{1,2}$/} ||
|
45
|
+
[path.first, 0]
|
46
|
+
sel = (el.selector =~ /^:{0,2}$/ ? el.selector : "")
|
47
|
+
[Node::Element.new(el.name, sel)] + path[i+1..-1]
|
48
|
+
end
|
49
|
+
|
50
|
+
def selector_str(path)
|
51
|
+
path.map {|e| e.sass_selector_str}.join(' ').gsub(' :', ':')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Property and variable declarations.
|
56
|
+
# We want to keep track of the line number
|
57
|
+
# so we don't space out the variables too much in the generated Sass.
|
58
|
+
module Declaration3
|
59
|
+
def build_with_sass(env)
|
60
|
+
build_without_sass(env)
|
61
|
+
env.rules.last.src_line = input.line_of(interval.first)
|
62
|
+
end
|
63
|
+
alias_method :build_without_sass, :build
|
64
|
+
alias_method :build, :build_with_sass
|
65
|
+
end
|
66
|
+
|
67
|
+
# Comma-separated selectors.
|
68
|
+
# Less breaks these into completely separate nodes.
|
69
|
+
# Since we don't want this duplication in the Sass,
|
70
|
+
# we modify the production to keep track of the original group
|
71
|
+
# so we can reconstruct it later on.
|
72
|
+
module Selectors2
|
73
|
+
def build_with_sass(env, method)
|
74
|
+
arr = build_without_sass(env, method)
|
75
|
+
return arr if method == :mixin
|
76
|
+
rarr = arr.map {|e| e.top(env)}
|
77
|
+
rarr.each {|e| e.group = rarr}
|
78
|
+
arr
|
79
|
+
end
|
80
|
+
alias_method :build_without_sass, :build
|
81
|
+
alias_method :build, :build_with_sass
|
82
|
+
end
|
83
|
+
|
84
|
+
# Attribute accessors.
|
85
|
+
# Sass just flat-out doesn't support these,
|
86
|
+
# so we print a warning to that effect and compile them to comments.
|
87
|
+
module Accessor1
|
88
|
+
def build(env)
|
89
|
+
Haml::Util.haml_warn <<WARNING
|
90
|
+
WARNING: Sass doesn't support attribute accessors.
|
91
|
+
Ignoring #{text_value}
|
92
|
+
WARNING
|
93
|
+
Node::Anonymous.new("/* #{text_value} */")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# @import statements.
|
98
|
+
# Less handles these during parse-time,
|
99
|
+
# so we want to wrap them up as a node in the tree.
|
100
|
+
# We also include the nodes, though,
|
101
|
+
# since we want to have access to the mixins
|
102
|
+
# so we can tell if they take arguments or not.
|
103
|
+
# The included nodes are hidden so they don't appear in the output.
|
104
|
+
module Import1
|
105
|
+
def build_with_sass(env)
|
106
|
+
line = input.line_of(interval.first)
|
107
|
+
import = Sass::Tree::ImportNode.new(url.value.gsub(/\.less$/, ''))
|
108
|
+
import.line = input.line_of(interval.first)
|
109
|
+
env << Node::SassNode.new(import)
|
110
|
+
old_rules = env.rules.dup
|
111
|
+
build_without_sass env
|
112
|
+
(env.rules - old_rules).each {|r| r.hide_in_sass = true}
|
113
|
+
rescue ImportError => e
|
114
|
+
raise Sass::SyntaxError.new("File to import #{url.text_value} not found or unreadable", :line => line)
|
115
|
+
end
|
116
|
+
alias_method :build_without_sass, :build
|
117
|
+
alias_method :build, :build_with_sass
|
118
|
+
end
|
119
|
+
|
120
|
+
# The IE-specific `alpha(opacity=@var)`.
|
121
|
+
# Less manually resolves the variable here at parse-time.
|
122
|
+
# We want to keep the variable around,
|
123
|
+
# so we compile this to a function.
|
124
|
+
# Less doesn't actually have an `=` operator,
|
125
|
+
# but that's okay since it's just getting compiled to Sass anyway.
|
126
|
+
module Entity::Alpha1
|
127
|
+
def build(env)
|
128
|
+
Node::Function.new("alpha",
|
129
|
+
[Node::Expression.new([
|
130
|
+
Node::Keyword.new("opacity"),
|
131
|
+
Node::Operator.new("="),
|
132
|
+
variable.build])])
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# The Less AST classes for the document,
|
138
|
+
# including both stylesheet-level nodes and expression-level nodes.
|
139
|
+
# The main purpose of overriding these is to add `#to_sass_tree` functions
|
140
|
+
# for converting to Sass.
|
141
|
+
module Node
|
142
|
+
module Entity
|
143
|
+
attr_accessor :hide_in_sass
|
144
|
+
attr_accessor :src_line
|
145
|
+
end
|
146
|
+
|
147
|
+
class Element
|
148
|
+
attr_accessor :group
|
149
|
+
|
150
|
+
def top(env)
|
151
|
+
return self if parent.equal?(env)
|
152
|
+
return parent.top(env)
|
153
|
+
end
|
154
|
+
|
155
|
+
def to_sass_tree
|
156
|
+
if root?
|
157
|
+
root = Sass::Tree::RootNode.new("")
|
158
|
+
rules.each {|r| root << r.to_sass_tree}
|
159
|
+
return root
|
160
|
+
end
|
161
|
+
return if hide_in_sass
|
162
|
+
return if !self.equal?(group.first)
|
163
|
+
|
164
|
+
last_el = nil
|
165
|
+
sel = group.map do |el|
|
166
|
+
comma_sel = []
|
167
|
+
loop do
|
168
|
+
comma_sel << el.sass_selector_str
|
169
|
+
break unless el.rules.size == 1 && el.rules.first.is_a?(Element)
|
170
|
+
el = el.rules.first
|
171
|
+
end
|
172
|
+
last_el = el
|
173
|
+
comma_sel = comma_sel.join(' ').gsub(' :', ':')
|
174
|
+
comma_sel.gsub!(/^:/, '&:') unless parent.root?
|
175
|
+
comma_sel
|
176
|
+
end.join(', ')
|
177
|
+
|
178
|
+
rule = Sass::Tree::RuleNode.new([sel])
|
179
|
+
last_el.rules.each {|r| rule << r.to_sass_tree}
|
180
|
+
return rule
|
181
|
+
end
|
182
|
+
|
183
|
+
def sass_selector_str
|
184
|
+
case @selector
|
185
|
+
when /[+>~]/; "#{@selector} #{@name}"
|
186
|
+
else @selector + @name
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
module Mixin
|
192
|
+
class Call
|
193
|
+
def to_sass_tree
|
194
|
+
return if hide_in_sass
|
195
|
+
Sass::Tree::MixinNode.new(@mixin.name.gsub(/^\./, ''), @params.map {|v| v.to_sass_tree})
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
class Def
|
200
|
+
def to_sass_tree
|
201
|
+
return if hide_in_sass
|
202
|
+
mixin = Sass::Tree::MixinDefNode.new(name, @params.map do |v|
|
203
|
+
v.value.flatten!
|
204
|
+
[Sass::Script::Variable.new(v), v.value.to_sass_tree]
|
205
|
+
end)
|
206
|
+
rules.each {|r| mixin << r.to_sass_tree}
|
207
|
+
mixin
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
class SassNode
|
213
|
+
include Entity
|
214
|
+
|
215
|
+
def initialize(node)
|
216
|
+
@node = node
|
217
|
+
end
|
218
|
+
|
219
|
+
def to_sass_tree
|
220
|
+
return if hide_in_sass
|
221
|
+
@node
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
class Property
|
226
|
+
def to_sass_tree
|
227
|
+
return if hide_in_sass
|
228
|
+
Sass::Tree::PropNode.new([self], @value.to_sass_tree, :new)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
class Expression
|
233
|
+
def to_sass_tree
|
234
|
+
if first.is_a?(Array)
|
235
|
+
val = map {|e| _to_sass_tree(e)}.inject(nil) do |e, i|
|
236
|
+
next i unless e
|
237
|
+
Sass::Script::Operation.new(e, i, :comma)
|
238
|
+
end
|
239
|
+
else
|
240
|
+
val = _to_sass_tree(self)
|
241
|
+
end
|
242
|
+
val.options = {}
|
243
|
+
val
|
244
|
+
end
|
245
|
+
|
246
|
+
private
|
247
|
+
|
248
|
+
LESS_TO_SASS_OPERATORS = {"-" => :minus, "+" => :plus, "*" => :times, "/" => :div, "=" => :single_eq}
|
249
|
+
def _to_sass_tree(arr)
|
250
|
+
return Sass::Script::UnaryOperation.new(_to_sass_tree(arr[1..-1]), :minus) if arr[0] == "-"
|
251
|
+
_to_sass_tree2(*_sass_split(arr))
|
252
|
+
end
|
253
|
+
|
254
|
+
def _to_sass_tree2(first, rest)
|
255
|
+
return first if rest.empty?
|
256
|
+
if rest[0].is_a?(Operator)
|
257
|
+
op = LESS_TO_SASS_OPERATORS[rest[0]]
|
258
|
+
if op == :times || op == :div
|
259
|
+
second, rest = _sass_split(rest[1..-1])
|
260
|
+
return _to_sass_tree2(Sass::Script::Operation.new(first, second, op), rest)
|
261
|
+
else
|
262
|
+
return Sass::Script::Operation.new(first, _to_sass_tree(rest[1..-1]), op)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
Sass::Script::Operation.new(first, _to_sass_tree(rest), :concat)
|
267
|
+
end
|
268
|
+
|
269
|
+
def _sass_split(arr)
|
270
|
+
return arr[0].to_sass_tree, arr[1..-1] unless arr[0] == "("
|
271
|
+
parens = 1
|
272
|
+
i = arr[1..-1].each_with_index do |e, i|
|
273
|
+
parens += 1 if e == "("
|
274
|
+
parens -= 1 if e == ")"
|
275
|
+
break i if parens == 0
|
276
|
+
end
|
277
|
+
|
278
|
+
return _to_sass_tree(arr[1...i+1]), arr[i+2..-1]
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
class Color
|
283
|
+
def to_sass_tree
|
284
|
+
Sass::Script::Color.new(:red => r, :green => g, :blue => b, :alpha => a)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
class Number
|
289
|
+
def to_sass_tree
|
290
|
+
Sass::Script::Number.new(self, [self.unit])
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
class Variable
|
295
|
+
def to_sass_tree
|
296
|
+
if @declaration
|
297
|
+
return if hide_in_sass
|
298
|
+
node = Sass::Tree::VariableNode.new(self, @value.to_sass_tree, false)
|
299
|
+
node.line = self.src_line
|
300
|
+
node
|
301
|
+
else
|
302
|
+
Sass::Script::Variable.new(self)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
class Function
|
308
|
+
def to_sass_tree
|
309
|
+
Sass::Script::Funcall.new(self, @args.map {|a| a.to_sass_tree})
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
class Keyword
|
314
|
+
def to_sass_tree
|
315
|
+
Sass::Script::String.new(self)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
class Anonymous
|
320
|
+
def to_sass_tree
|
321
|
+
Sass::Script::String.new(self)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
class Quoted
|
326
|
+
def to_sass_tree
|
327
|
+
Sass::Script::String.new(self, true)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
class FontFamily
|
332
|
+
def to_sass_tree
|
333
|
+
@family.map {|f| f.to_sass_tree}.inject(nil) do |e, f|
|
334
|
+
next f unless e
|
335
|
+
Sass::Script::Operation.new(e, f, :comma)
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
# The entry point to Less.
|
342
|
+
# By default Less doesn't preserve the filename of the file being parsed,
|
343
|
+
# which is unpleasant for error reporting.
|
344
|
+
# Our monkeypatch keeps it around.
|
345
|
+
class Engine
|
346
|
+
def initialize_with_sass(obj, opts = {})
|
347
|
+
initialize_without_sass(obj, opts)
|
348
|
+
@filename = obj.path if obj.is_a?(File)
|
349
|
+
end
|
350
|
+
alias_method :initialize_without_sass, :initialize
|
351
|
+
alias_method :initialize, :initialize_with_sass
|
352
|
+
|
353
|
+
def parse_with_sass
|
354
|
+
parse_without_sass
|
355
|
+
rescue Sass::SyntaxError => e
|
356
|
+
e.modify_backtrace(:filename => @filename)
|
357
|
+
raise e
|
358
|
+
end
|
359
|
+
alias_method :parse_without_sass, :parse
|
360
|
+
alias_method :parse, :parse_with_sass
|
361
|
+
alias_method :to_tree, :parse
|
362
|
+
end
|
363
|
+
end
|
@@ -0,0 +1,625 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'sass/less'
|
6
|
+
|
7
|
+
class LessConversionTest < Test::Unit::TestCase
|
8
|
+
def test_variable_declarations
|
9
|
+
assert_renders <<SCSS, <<LESS
|
10
|
+
$var1: 2px 3px;
|
11
|
+
$var2: $var1 + 7px;
|
12
|
+
|
13
|
+
$var3: fizz;
|
14
|
+
|
15
|
+
foo {
|
16
|
+
prop: $var1 $var2 $var3; }
|
17
|
+
SCSS
|
18
|
+
@var1: 2px 3px;
|
19
|
+
@var2: @var1 + 7px;
|
20
|
+
|
21
|
+
@var3: fizz;
|
22
|
+
|
23
|
+
foo {prop: @var1 @var2 @var3}
|
24
|
+
LESS
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_nested_variable_declarations
|
28
|
+
assert_renders <<SCSS, <<LESS
|
29
|
+
.foo {
|
30
|
+
$var: 2px;
|
31
|
+
prop: $var; }
|
32
|
+
SCSS
|
33
|
+
.foo {
|
34
|
+
@var: 2px;
|
35
|
+
prop: @var; }
|
36
|
+
LESS
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_import
|
40
|
+
path = File.dirname(__FILE__) + "/templates/importee.less"
|
41
|
+
resolved_path = File.dirname(__FILE__) + "/templates/importee"
|
42
|
+
assert_renders <<SCSS, <<LESS
|
43
|
+
@import "#{resolved_path}";
|
44
|
+
@import "#{resolved_path}";
|
45
|
+
|
46
|
+
@import "#{resolved_path}";
|
47
|
+
@import "#{resolved_path}";
|
48
|
+
@import "#{resolved_path}";
|
49
|
+
SCSS
|
50
|
+
@import url(#{path});
|
51
|
+
@import url("#{path}");
|
52
|
+
|
53
|
+
@import url('#{path}');
|
54
|
+
@import '#{path}';
|
55
|
+
@import "#{path}";
|
56
|
+
LESS
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_mixins_found_through_import
|
60
|
+
path = File.dirname(__FILE__) + "/templates/importee.less"
|
61
|
+
resolved_path = File.dirname(__FILE__) + "/templates/importee"
|
62
|
+
assert_renders <<SCSS, <<LESS
|
63
|
+
@import "#{resolved_path}";
|
64
|
+
|
65
|
+
.baz {
|
66
|
+
@extend .foo;
|
67
|
+
@include bar; }
|
68
|
+
SCSS
|
69
|
+
@import "#{path}";
|
70
|
+
|
71
|
+
.baz {.foo; .bar;}
|
72
|
+
LESS
|
73
|
+
end
|
74
|
+
|
75
|
+
# Selectors
|
76
|
+
|
77
|
+
def test_element_selector
|
78
|
+
assert_renders <<SCSS, <<LESS
|
79
|
+
foo {
|
80
|
+
a: b; }
|
81
|
+
SCSS
|
82
|
+
foo {a: b}
|
83
|
+
LESS
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_class_selector
|
87
|
+
assert_renders <<SCSS, <<LESS
|
88
|
+
.foo {
|
89
|
+
a: b; }
|
90
|
+
SCSS
|
91
|
+
.foo {a: b}
|
92
|
+
LESS
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_id_selector
|
96
|
+
assert_renders <<SCSS, <<LESS
|
97
|
+
#foo {
|
98
|
+
a: b; }
|
99
|
+
SCSS
|
100
|
+
#foo {a: b}
|
101
|
+
LESS
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_pseudoclass_selector
|
105
|
+
assert_renders <<SCSS, <<LESS
|
106
|
+
:foo {
|
107
|
+
a: b; }
|
108
|
+
SCSS
|
109
|
+
:foo {a: b}
|
110
|
+
LESS
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_pseudoelement_selector
|
114
|
+
assert_renders <<SCSS, <<LESS
|
115
|
+
::foo {
|
116
|
+
a: b; }
|
117
|
+
SCSS
|
118
|
+
::foo {a: b}
|
119
|
+
LESS
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_comma_selector
|
123
|
+
assert_renders <<SCSS, <<LESS
|
124
|
+
foo, .bar .baz, :bang {
|
125
|
+
a: b; }
|
126
|
+
SCSS
|
127
|
+
foo, .bar .baz, :bang {a: b}
|
128
|
+
LESS
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_nested_comma_selector
|
132
|
+
assert_renders <<SCSS, <<LESS
|
133
|
+
foo bar, .baz {
|
134
|
+
.bang, &:bip bap {
|
135
|
+
a: b; } }
|
136
|
+
SCSS
|
137
|
+
foo bar, .baz {
|
138
|
+
.bang, :bip bap {a: b} }
|
139
|
+
LESS
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_simple_selector_sequence
|
143
|
+
assert_renders <<SCSS, <<LESS
|
144
|
+
a.foo#bar[attr=val] {
|
145
|
+
a: b; }
|
146
|
+
SCSS
|
147
|
+
a.foo#bar[attr=val] {a: b}
|
148
|
+
LESS
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_descendant_selector
|
152
|
+
assert_renders <<SCSS, <<LESS
|
153
|
+
.foo .bar {
|
154
|
+
a: b; }
|
155
|
+
SCSS
|
156
|
+
.foo .bar {a: b}
|
157
|
+
LESS
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_child_selector
|
161
|
+
assert_renders <<SCSS, <<LESS
|
162
|
+
.foo > .bar {
|
163
|
+
a: b; }
|
164
|
+
SCSS
|
165
|
+
.foo > .bar {a: b}
|
166
|
+
LESS
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_adjacent_selector
|
170
|
+
assert_renders <<SCSS, <<LESS
|
171
|
+
.foo + .bar {
|
172
|
+
a: b; }
|
173
|
+
SCSS
|
174
|
+
.foo + .bar {a: b}
|
175
|
+
LESS
|
176
|
+
end
|
177
|
+
|
178
|
+
def test_pseudoclass_in_sequence
|
179
|
+
assert_renders <<SCSS, <<LESS
|
180
|
+
.foo:bar {
|
181
|
+
a: b; }
|
182
|
+
SCSS
|
183
|
+
.foo:bar {a: b}
|
184
|
+
LESS
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_pseudoelement_in_sequence
|
188
|
+
assert_renders <<SCSS, <<LESS
|
189
|
+
.foo::bar {
|
190
|
+
a: b; }
|
191
|
+
SCSS
|
192
|
+
.foo::bar {a: b}
|
193
|
+
LESS
|
194
|
+
end
|
195
|
+
|
196
|
+
# Properties
|
197
|
+
|
198
|
+
def test_space_separated_props
|
199
|
+
assert_renders <<SCSS, <<LESS
|
200
|
+
foo {
|
201
|
+
a: foo bar baz; }
|
202
|
+
SCSS
|
203
|
+
foo {a: foo bar baz}
|
204
|
+
LESS
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_comma_separated_props
|
208
|
+
assert_renders <<SCSS, <<LESS
|
209
|
+
foo {
|
210
|
+
a: foo, bar, baz; }
|
211
|
+
SCSS
|
212
|
+
foo {a: foo, bar, baz}
|
213
|
+
LESS
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_numbers
|
217
|
+
assert_renders <<SCSS, <<LESS
|
218
|
+
foo {
|
219
|
+
a: 1 2.3 -8 5px 3%; }
|
220
|
+
SCSS
|
221
|
+
foo {a: 1 2.3 -8 5px 3%}
|
222
|
+
LESS
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_colors
|
226
|
+
assert_renders <<SCSS, <<LESS
|
227
|
+
foo {
|
228
|
+
a: red #abcdef blue; }
|
229
|
+
SCSS
|
230
|
+
foo {a: #f00 #abcdef blue}
|
231
|
+
LESS
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_strings
|
235
|
+
assert_renders <<SCSS, <<LESS
|
236
|
+
foo {
|
237
|
+
a: "foo @var bar" "baz bang" "quote'quote" 'quote"quote'; }
|
238
|
+
SCSS
|
239
|
+
foo {a: "foo @var bar" 'baz bang' "quote'quote" 'quote"quote'}
|
240
|
+
LESS
|
241
|
+
end
|
242
|
+
|
243
|
+
def test_slash
|
244
|
+
assert_renders <<SCSS, <<LESS
|
245
|
+
foo {
|
246
|
+
a: small/8px 7em/8px;
|
247
|
+
b: 8/4;
|
248
|
+
c: (8 / 4); }
|
249
|
+
SCSS
|
250
|
+
foo {
|
251
|
+
a: small/8px 7em/8px;
|
252
|
+
b: 8/4;
|
253
|
+
c: 8 / 4; }
|
254
|
+
LESS
|
255
|
+
end
|
256
|
+
|
257
|
+
def test_url
|
258
|
+
assert_renders <<SCSS, <<LESS
|
259
|
+
foo {
|
260
|
+
a: url("http://foobar.com/fizzle.html?foo=bar&bar=baz");
|
261
|
+
b: url("http://foobar.com/fizzle.html?foo=bar&bar=baz");
|
262
|
+
c: url("http://foobar.com/fizzle.html?foo=bar&bar=baz"); }
|
263
|
+
SCSS
|
264
|
+
foo {
|
265
|
+
a: url(http://foobar.com/fizzle.html?foo=bar&bar=baz);
|
266
|
+
b: url("http://foobar.com/fizzle.html?foo=bar&bar=baz");
|
267
|
+
c: url('http://foobar.com/fizzle.html?foo=bar&bar=baz'); }
|
268
|
+
LESS
|
269
|
+
end
|
270
|
+
|
271
|
+
def test_functions
|
272
|
+
assert_renders <<SCSS, <<LESS
|
273
|
+
foo {
|
274
|
+
a: baz(12px) rgba(80, 70 120, 0.76);
|
275
|
+
b: faz(1px + 3px) bang($var, #aaaaaa * 3); }
|
276
|
+
SCSS
|
277
|
+
foo {
|
278
|
+
a: baz(12px) rgba(80, 70 120, 0.76);
|
279
|
+
b: faz(1px + 3px) bang(@var, #aaa * 3); }
|
280
|
+
LESS
|
281
|
+
end
|
282
|
+
|
283
|
+
def test_alpha_function
|
284
|
+
assert_renders <<SCSS, <<LESS
|
285
|
+
foo {
|
286
|
+
a: alpha(opacity=2px);
|
287
|
+
b: alpha(opacity = $var); }
|
288
|
+
SCSS
|
289
|
+
foo {
|
290
|
+
a: alpha(opacity=2px);
|
291
|
+
b: alpha(opacity=@var); }
|
292
|
+
LESS
|
293
|
+
end
|
294
|
+
|
295
|
+
def test_variables
|
296
|
+
assert_renders <<SCSS, <<LESS
|
297
|
+
foo {
|
298
|
+
a: $var1 $var-foo; }
|
299
|
+
SCSS
|
300
|
+
foo {a: @var1 @var-foo}
|
301
|
+
LESS
|
302
|
+
end
|
303
|
+
|
304
|
+
def test_operators
|
305
|
+
assert_renders <<SCSS, <<LESS
|
306
|
+
foo {
|
307
|
+
a: 1px + 2px;
|
308
|
+
b: #bbaa88 - #aa1122;
|
309
|
+
c: 5 * 3;
|
310
|
+
d: (8 / 4); }
|
311
|
+
SCSS
|
312
|
+
foo {
|
313
|
+
a: 1px + 2px;
|
314
|
+
b: #ba8 - #a12;
|
315
|
+
c: 5 * 3;
|
316
|
+
d: 8 / 4; }
|
317
|
+
LESS
|
318
|
+
end
|
319
|
+
|
320
|
+
def test_operator_precedence
|
321
|
+
assert_renders <<SCSS, <<LESS
|
322
|
+
foo {
|
323
|
+
a: 1 + 2 * 3 + 4;
|
324
|
+
b: 1 * 2 + 3 * 4;
|
325
|
+
c: 1 - 2 + 2 - 4;
|
326
|
+
d: 1 + 2 - 3 + 4;
|
327
|
+
e: 1 / 2 - 3 / 4;
|
328
|
+
f: 1 - 2 / 3 - 4;
|
329
|
+
g: 1 / 2 * 3 / 4; }
|
330
|
+
SCSS
|
331
|
+
foo {
|
332
|
+
a: 1 + 2 * 3 + 4;
|
333
|
+
b: 1 * 2 + 3 * 4;
|
334
|
+
c: 1 - 2 + 2 - 4;
|
335
|
+
d: 1 + 2 - 3 + 4;
|
336
|
+
e: 1 / 2 - 3 / 4;
|
337
|
+
f: 1 - 2 / 3 - 4;
|
338
|
+
g: 1 / 2 * 3 / 4; }
|
339
|
+
LESS
|
340
|
+
end
|
341
|
+
|
342
|
+
def test_operators_with_parens
|
343
|
+
assert_renders <<SCSS, <<LESS
|
344
|
+
foo {
|
345
|
+
a: 1px + 2px * 3;
|
346
|
+
b: (1px - 2px) / 3; }
|
347
|
+
SCSS
|
348
|
+
foo {
|
349
|
+
a: 1px + (2px * 3);
|
350
|
+
b: (1px - (2px)) / 3; }
|
351
|
+
LESS
|
352
|
+
end
|
353
|
+
|
354
|
+
def test_unary_minus
|
355
|
+
assert_renders <<SCSS, <<LESS
|
356
|
+
foo {
|
357
|
+
a: 1px + -3px; }
|
358
|
+
SCSS
|
359
|
+
foo {a: 1px + (- 3px)}
|
360
|
+
LESS
|
361
|
+
end
|
362
|
+
|
363
|
+
# Nested Rules
|
364
|
+
|
365
|
+
def test_single_nested_rule
|
366
|
+
assert_renders <<SCSS, <<LESS
|
367
|
+
foo bar {
|
368
|
+
a: b; }
|
369
|
+
SCSS
|
370
|
+
foo {bar {a: b}}
|
371
|
+
LESS
|
372
|
+
end
|
373
|
+
|
374
|
+
def test_single_nested_rule_with_props
|
375
|
+
assert_renders <<SCSS, <<LESS
|
376
|
+
foo {
|
377
|
+
bar {
|
378
|
+
a: b; }
|
379
|
+
c: d;
|
380
|
+
e: f; }
|
381
|
+
SCSS
|
382
|
+
foo {
|
383
|
+
bar {a: b}
|
384
|
+
c: d;
|
385
|
+
e: f; }
|
386
|
+
LESS
|
387
|
+
end
|
388
|
+
|
389
|
+
def test_two_nested_rules
|
390
|
+
assert_renders <<SCSS, <<LESS
|
391
|
+
foo {
|
392
|
+
bar {
|
393
|
+
a: b; }
|
394
|
+
baz {
|
395
|
+
c: d; } }
|
396
|
+
SCSS
|
397
|
+
foo {
|
398
|
+
bar {a: b}
|
399
|
+
baz {c: d} }
|
400
|
+
LESS
|
401
|
+
end
|
402
|
+
|
403
|
+
def test_two_nested_rules_with_props
|
404
|
+
assert_renders <<SCSS, <<LESS
|
405
|
+
foo {
|
406
|
+
bar {
|
407
|
+
a: b; }
|
408
|
+
baz {
|
409
|
+
c: d; }
|
410
|
+
e: f;
|
411
|
+
g: h; }
|
412
|
+
SCSS
|
413
|
+
foo {
|
414
|
+
bar {a: b}
|
415
|
+
baz {c: d}
|
416
|
+
e: f;
|
417
|
+
g: h; }
|
418
|
+
LESS
|
419
|
+
end
|
420
|
+
|
421
|
+
def test_nested_rules_with_combinators
|
422
|
+
assert_renders <<SCSS, <<LESS
|
423
|
+
foo {
|
424
|
+
> bar {
|
425
|
+
a: b; }
|
426
|
+
+ baz {
|
427
|
+
c: d; } }
|
428
|
+
SCSS
|
429
|
+
foo {
|
430
|
+
> bar {a: b}
|
431
|
+
+ baz {c: d} }
|
432
|
+
LESS
|
433
|
+
end
|
434
|
+
|
435
|
+
def test_nested_pseudo_rules
|
436
|
+
assert_renders <<SCSS, <<LESS
|
437
|
+
foo {
|
438
|
+
&:bar {
|
439
|
+
a: b; }
|
440
|
+
&::baz {
|
441
|
+
c: d; } }
|
442
|
+
SCSS
|
443
|
+
foo {
|
444
|
+
:bar {a: b}
|
445
|
+
::baz {c: d} }
|
446
|
+
LESS
|
447
|
+
end
|
448
|
+
|
449
|
+
# Mixins
|
450
|
+
|
451
|
+
def test_class_inheritance
|
452
|
+
assert_renders <<SCSS, <<LESS
|
453
|
+
.foo {
|
454
|
+
a: b; }
|
455
|
+
|
456
|
+
.bar {
|
457
|
+
@extend .foo; }
|
458
|
+
SCSS
|
459
|
+
.foo {a: b}
|
460
|
+
.bar {.foo;}
|
461
|
+
LESS
|
462
|
+
end
|
463
|
+
|
464
|
+
def test_multiple_class_inheritance
|
465
|
+
assert_renders <<SCSS, <<LESS
|
466
|
+
.foo {
|
467
|
+
a: b; }
|
468
|
+
|
469
|
+
.bar {
|
470
|
+
c: d; }
|
471
|
+
|
472
|
+
.baz {
|
473
|
+
@extend .foo;
|
474
|
+
@extend .bar; }
|
475
|
+
SCSS
|
476
|
+
.foo {a: b}
|
477
|
+
.bar {c: d}
|
478
|
+
.baz {.foo, .bar;}
|
479
|
+
LESS
|
480
|
+
end
|
481
|
+
|
482
|
+
def test_pseudoclass_inheritance
|
483
|
+
assert_renders <<SCSS, <<LESS
|
484
|
+
:foo {
|
485
|
+
a: b; }
|
486
|
+
|
487
|
+
:bar {
|
488
|
+
@extend :foo; }
|
489
|
+
SCSS
|
490
|
+
:foo {a: b}
|
491
|
+
:bar {:foo;}
|
492
|
+
LESS
|
493
|
+
end
|
494
|
+
|
495
|
+
def test_multiple_pseudoclass_inheritance
|
496
|
+
assert_renders <<SCSS, <<LESS
|
497
|
+
:foo:bar {
|
498
|
+
a: b; }
|
499
|
+
|
500
|
+
:baz {
|
501
|
+
@extend :foo:bar; }
|
502
|
+
SCSS
|
503
|
+
:foo:bar {a: b}
|
504
|
+
:baz {:foo:bar;}
|
505
|
+
LESS
|
506
|
+
end
|
507
|
+
|
508
|
+
def test_abstract_mixin
|
509
|
+
assert_renders <<SCSS, <<LESS
|
510
|
+
@mixin foo {
|
511
|
+
a: b; }
|
512
|
+
|
513
|
+
.bar {
|
514
|
+
@include foo; }
|
515
|
+
SCSS
|
516
|
+
.foo() {a: b}
|
517
|
+
.bar {.foo;}
|
518
|
+
LESS
|
519
|
+
end
|
520
|
+
|
521
|
+
def test_mixin_with_args
|
522
|
+
assert_renders <<SCSS, <<LESS
|
523
|
+
@mixin foo($a: 2px, $b: red) {
|
524
|
+
a: $a; }
|
525
|
+
|
526
|
+
.bar {
|
527
|
+
@include foo; }
|
528
|
+
SCSS
|
529
|
+
.foo(@a: 2px, @b: #f00) {a: @a}
|
530
|
+
.bar {.foo;}
|
531
|
+
LESS
|
532
|
+
|
533
|
+
assert_renders <<SCSS, <<LESS
|
534
|
+
@mixin foo($a: 2px + 3px, $b: red) {
|
535
|
+
a: $a; }
|
536
|
+
|
537
|
+
.bar {
|
538
|
+
@include foo(5px); }
|
539
|
+
SCSS
|
540
|
+
.foo(@a: 2px + 3px, @b: #f00) {a: @a}
|
541
|
+
.bar {.foo(5px);}
|
542
|
+
LESS
|
543
|
+
end
|
544
|
+
|
545
|
+
## Disallowed Mixins
|
546
|
+
|
547
|
+
def test_nested_mixin
|
548
|
+
assert_warning(<<WARN) {assert_renders <<SCSS, <<LESS}
|
549
|
+
WARNING: Sass doesn't support mixing in selector sequences.
|
550
|
+
Replacing ".foo .bar" with "@extend .bar"
|
551
|
+
WARN
|
552
|
+
.foo .bar {
|
553
|
+
a: b; }
|
554
|
+
|
555
|
+
.bar {
|
556
|
+
// .foo .bar;
|
557
|
+
@extend .bar; }
|
558
|
+
SCSS
|
559
|
+
.foo .bar {a: b}
|
560
|
+
.bar {.foo .bar;}
|
561
|
+
LESS
|
562
|
+
end
|
563
|
+
|
564
|
+
def test_child_selector_mixin
|
565
|
+
assert_warning(<<WARN) {assert_renders <<SCSS, <<LESS}
|
566
|
+
WARNING: Sass doesn't support mixing in selector sequences.
|
567
|
+
Replacing "> .bar" with "@extend .bar"
|
568
|
+
WARN
|
569
|
+
.foo > .bar {
|
570
|
+
a: b; }
|
571
|
+
|
572
|
+
.bar {
|
573
|
+
// > .bar;
|
574
|
+
@extend .bar; }
|
575
|
+
SCSS
|
576
|
+
.foo > .bar {a: b}
|
577
|
+
.bar {> .bar;}
|
578
|
+
LESS
|
579
|
+
end
|
580
|
+
|
581
|
+
# Accessors
|
582
|
+
|
583
|
+
def test_property_accessor
|
584
|
+
assert_warning(<<WARN) {assert_renders <<SCSS, <<LESS}
|
585
|
+
WARNING: Sass doesn't support attribute accessors.
|
586
|
+
Ignoring .magic-box['content']
|
587
|
+
WARN
|
588
|
+
.magic-box {
|
589
|
+
content: "gold"; }
|
590
|
+
|
591
|
+
.foo {
|
592
|
+
content: /* .magic-box['content'] */; }
|
593
|
+
SCSS
|
594
|
+
.magic-box {content: "gold"}
|
595
|
+
.foo {content: .magic-box['content']}
|
596
|
+
LESS
|
597
|
+
end
|
598
|
+
|
599
|
+
def test_variable_accessor
|
600
|
+
assert_warning(<<WARN) {assert_renders <<SCSS, <<LESS}
|
601
|
+
WARNING: Sass doesn't support attribute accessors.
|
602
|
+
Ignoring .magic-box[@content]
|
603
|
+
WARN
|
604
|
+
.magic-box {
|
605
|
+
$content: "gold";
|
606
|
+
content: $content; }
|
607
|
+
|
608
|
+
.foo {
|
609
|
+
content: /* .magic-box[@content] */; }
|
610
|
+
SCSS
|
611
|
+
.magic-box {@content: "gold"; content: @content}
|
612
|
+
.foo {content: .magic-box[@content]}
|
613
|
+
LESS
|
614
|
+
end
|
615
|
+
|
616
|
+
private
|
617
|
+
|
618
|
+
def assert_renders(scss, less)
|
619
|
+
assert_equal(scss, Less::Engine.new(less).to_tree.to_sass_tree.to_scss)
|
620
|
+
end
|
621
|
+
end
|
622
|
+
|
623
|
+
rescue LoadError => e
|
624
|
+
puts "\nCouldn't require less, skipping some tests."
|
625
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: haml-edge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.3.
|
4
|
+
version: 2.3.241
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Weizenbaum
|
@@ -69,9 +69,9 @@ files:
|
|
69
69
|
- lib/haml/template.rb
|
70
70
|
- lib/haml/shared.rb
|
71
71
|
- lib/haml/util.rb
|
72
|
+
- lib/haml/template/options.rb
|
72
73
|
- lib/haml/template/patch.rb
|
73
74
|
- lib/haml/template/plugin.rb
|
74
|
-
- lib/haml/template/options.rb
|
75
75
|
- lib/haml/version.rb
|
76
76
|
- lib/haml/html/erb.rb
|
77
77
|
- lib/haml/root.rb
|
@@ -137,6 +137,7 @@ files:
|
|
137
137
|
- lib/sass/selector/sequence.rb
|
138
138
|
- lib/sass/selector/simple.rb
|
139
139
|
- lib/sass/selector/simple_sequence.rb
|
140
|
+
- lib/sass/less.rb
|
140
141
|
- vendor/fssm/LICENSE
|
141
142
|
- vendor/fssm/README.markdown
|
142
143
|
- vendor/fssm/Rakefile
|
@@ -312,10 +313,12 @@ files:
|
|
312
313
|
- test/sass/templates/scss_importee.scss
|
313
314
|
- test/sass/templates/warn.sass
|
314
315
|
- test/sass/templates/warn_imported.sass
|
316
|
+
- test/sass/templates/importee.less
|
315
317
|
- test/sass/scss/css_test.rb
|
316
318
|
- test/sass/scss/rx_test.rb
|
317
319
|
- test/sass/scss/scss_test.rb
|
318
320
|
- test/sass/scss/test_helper.rb
|
321
|
+
- test/sass/less_conversion_test.rb
|
319
322
|
- test/test_helper.rb
|
320
323
|
- extra/haml-mode.el
|
321
324
|
- extra/sass-mode.el
|
@@ -386,3 +389,4 @@ test_files:
|
|
386
389
|
- test/sass/scss/css_test.rb
|
387
390
|
- test/sass/scss/rx_test.rb
|
388
391
|
- test/sass/scss/scss_test.rb
|
392
|
+
- test/sass/less_conversion_test.rb
|