haml 3.0.0.rc.3 → 3.0.0.rc.4
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/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/haml/exec.rb +36 -12
- data/lib/haml/helpers/action_view_mods.rb +16 -0
- data/lib/haml/railtie.rb +1 -0
- data/lib/haml/template.rb +1 -9
- data/lib/haml/template/options.rb +16 -0
- data/lib/sass/less.rb +363 -0
- data/lib/sass/plugin/rails.rb +1 -1
- data/lib/sass/tree/for_node.rb +12 -0
- data/lib/sass/tree/if_node.rb +12 -0
- data/lib/sass/tree/root_node.rb +2 -1
- data/lib/sass/tree/while_node.rb +12 -0
- data/test/haml/template_test.rb +11 -0
- data/test/sass/conversion_test.rb +18 -0
- data/test/sass/extend_test.rb +67 -0
- data/test/sass/less_conversion_test.rb +625 -0
- data/test/sass/templates/importee.less +2 -0
- metadata +8 -3
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
|
-
3.0.0.rc.
|
1
|
+
3.0.0.rc.4
|
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
|
@@ -169,6 +169,22 @@ module ActionView
|
|
169
169
|
alias_method :form_for_without_haml, :form_for
|
170
170
|
alias_method :form_for, :form_for_with_haml
|
171
171
|
end
|
172
|
+
|
173
|
+
module CacheHelper
|
174
|
+
# This is a workaround for a Rails 3 bug
|
175
|
+
# that's present at least through beta 3.
|
176
|
+
# Their fragment_for assumes that the block
|
177
|
+
# will return its contents as a string,
|
178
|
+
# which is not always the case.
|
179
|
+
# Luckily, it only makes this assumption if caching is disabled,
|
180
|
+
# so we only override that case.
|
181
|
+
def fragment_for_with_haml(*args, &block)
|
182
|
+
return fragment_for_without_haml(*args, &block) if controller.perform_caching
|
183
|
+
capture(&block)
|
184
|
+
end
|
185
|
+
alias_method :fragment_for_without_haml, :fragment_for
|
186
|
+
alias_method :fragment_for, :fragment_for_with_haml
|
187
|
+
end
|
172
188
|
else
|
173
189
|
module FormTagHelper
|
174
190
|
def form_tag_with_haml(url_for_options = {}, options = {}, *parameters_for_url, &proc)
|
data/lib/haml/railtie.rb
CHANGED
data/lib/haml/template.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'haml/template/options'
|
1
2
|
require 'haml/engine'
|
2
3
|
require 'haml/helpers/action_view_mods'
|
3
4
|
require 'haml/helpers/action_view_extensions'
|
@@ -5,15 +6,6 @@ require 'haml/helpers/action_view_extensions'
|
|
5
6
|
module Haml
|
6
7
|
# The class that keeps track of the global options for Haml within Rails.
|
7
8
|
module Template
|
8
|
-
extend self
|
9
|
-
|
10
|
-
@options = {}
|
11
|
-
# The options hash for Haml when used within Rails.
|
12
|
-
# See {file:HAML_REFERENCE.md#haml_options the Haml options documentation}.
|
13
|
-
#
|
14
|
-
# @return [{Symbol => Object}]
|
15
|
-
attr_accessor :options
|
16
|
-
|
17
9
|
# Enables integration with the Rails 2.2.5+ XSS protection,
|
18
10
|
# if it's available and enabled.
|
19
11
|
#
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# We keep options in its own self-contained file
|
2
|
+
# so that we can load it independently in Rails 3,
|
3
|
+
# where the full template stuff is lazy-loaded.
|
4
|
+
|
5
|
+
module Haml
|
6
|
+
module Template
|
7
|
+
extend self
|
8
|
+
|
9
|
+
@options = {}
|
10
|
+
# The options hash for Haml when used within Rails.
|
11
|
+
# See {file:HAML_REFERENCE.md#haml_options the Haml options documentation}.
|
12
|
+
#
|
13
|
+
# @return [{Symbol => Object}]
|
14
|
+
attr_accessor :options
|
15
|
+
end
|
16
|
+
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
|