haml 3.0.0.beta.1 → 3.0.0.beta.2
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/README.md +7 -7
- data/REMEMBER +2 -1
- data/Rakefile +6 -4
- data/VERSION +1 -1
- data/lib/haml/exec.rb +119 -24
- data/lib/haml/filters.rb +5 -1
- data/lib/haml/helpers.rb +4 -2
- data/lib/haml/helpers/action_view_mods.rb +2 -3
- data/lib/haml/precompiler.rb +1 -0
- data/lib/sass.rb +1 -1
- data/lib/sass/css.rb +25 -6
- data/lib/sass/engine.rb +23 -7
- data/lib/sass/environment.rb +47 -1
- data/lib/sass/files.rb +9 -10
- data/lib/sass/plugin.rb +6 -27
- data/lib/sass/plugin/merb.rb +1 -0
- data/lib/sass/plugin/rails.rb +1 -0
- data/lib/sass/plugin/staleness_checker.rb +123 -0
- data/lib/sass/script/bool.rb +1 -1
- data/lib/sass/script/color.rb +1 -1
- data/lib/sass/script/css_lexer.rb +1 -4
- data/lib/sass/script/funcall.rb +2 -2
- data/lib/sass/script/functions.rb +102 -7
- data/lib/sass/script/interpolation.rb +5 -5
- data/lib/sass/script/lexer.rb +10 -8
- data/lib/sass/script/literal.rb +11 -1
- data/lib/sass/script/node.rb +10 -1
- data/lib/sass/script/number.rb +25 -10
- data/lib/sass/script/operation.rb +7 -6
- data/lib/sass/script/parser.rb +37 -28
- data/lib/sass/script/string.rb +12 -7
- data/lib/sass/script/string_interpolation.rb +70 -0
- data/lib/sass/script/unary_operation.rb +3 -3
- data/lib/sass/script/variable.rb +2 -2
- data/lib/sass/scss/css_parser.rb +1 -0
- data/lib/sass/scss/parser.rb +58 -44
- data/lib/sass/scss/rx.rb +1 -0
- data/lib/sass/tree/comment_node.rb +3 -2
- data/lib/sass/tree/debug_node.rb +1 -1
- data/lib/sass/tree/for_node.rb +1 -1
- data/lib/sass/tree/if_node.rb +1 -1
- data/lib/sass/tree/import_node.rb +3 -0
- data/lib/sass/tree/mixin_def_node.rb +3 -3
- data/lib/sass/tree/mixin_node.rb +7 -3
- data/lib/sass/tree/node.rb +8 -0
- data/lib/sass/tree/prop_node.rb +21 -16
- data/lib/sass/tree/rule_node.rb +3 -3
- data/lib/sass/tree/variable_node.rb +1 -1
- data/lib/sass/tree/warn_node.rb +41 -0
- data/lib/sass/tree/while_node.rb +1 -1
- data/test/haml/engine_test.rb +9 -0
- data/test/sass/conversion_test.rb +127 -15
- data/test/sass/css2sass_test.rb +34 -3
- data/test/sass/engine_test.rb +82 -5
- data/test/sass/functions_test.rb +31 -0
- data/test/sass/plugin_test.rb +25 -24
- data/test/sass/results/script.css +4 -4
- data/test/sass/results/warn.css +0 -0
- data/test/sass/results/warn_imported.css +0 -0
- data/test/sass/script_conversion_test.rb +43 -1
- data/test/sass/script_test.rb +3 -3
- data/test/sass/scss/css_test.rb +46 -5
- data/test/sass/scss/scss_test.rb +72 -0
- data/test/sass/templates/import.sass +1 -1
- data/test/sass/templates/warn.sass +3 -0
- data/test/sass/templates/warn_imported.sass +4 -0
- metadata +10 -3
data/README.md
CHANGED
@@ -38,7 +38,7 @@ Sass is a little more complicated;
|
|
38
38
|
where they'll be automatically compiled
|
39
39
|
to corresponding CSS files in `public/stylesheets` when needed
|
40
40
|
(the Sass template directory is customizable...
|
41
|
-
see [the Sass reference](http://sass-lang.com/docs/yardoc/SASS_REFERENCE.
|
41
|
+
see [the Sass reference](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#template_location-option) for details).
|
42
42
|
|
43
43
|
For Merb, `.html.haml` views will work without any further modification.
|
44
44
|
To enable Sass, you also need to add a dependency.
|
@@ -129,7 +129,7 @@ like `if` and `while`:
|
|
129
129
|
= "Happy new " + "year!"
|
130
130
|
|
131
131
|
Haml provides far more tools than those presented here.
|
132
|
-
Check out the [reference documentation](http://beta.haml-lang.com/docs/yardoc/file.HAML_REFERENCE.
|
132
|
+
Check out the [reference documentation](http://beta.haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html)
|
133
133
|
for full details.
|
134
134
|
|
135
135
|
#### Indentation
|
@@ -151,10 +151,10 @@ and get small stylesheets up and running quickly,
|
|
151
151
|
particularly with the help of
|
152
152
|
[the Compass style library](http://compass-style.org).
|
153
153
|
|
154
|
-
[vars]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.
|
155
|
-
[nested]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.
|
154
|
+
[vars]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#variables_
|
155
|
+
[nested]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#nested_rules_
|
156
156
|
[mixins]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#mixins
|
157
|
-
[imports]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.
|
157
|
+
[imports]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#import
|
158
158
|
|
159
159
|
Sass has two syntaxes.
|
160
160
|
The one presented here, known as "SCSS" (for "Sassy CSS"),
|
@@ -163,7 +163,7 @@ The other (older) syntax, known as the indented syntax or just "Sass",
|
|
163
163
|
is whitespace-sensitive and indentation-based.
|
164
164
|
For more information, see the [reference documentation][syntax].
|
165
165
|
|
166
|
-
[syntax]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.
|
166
|
+
[syntax]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#syntax
|
167
167
|
|
168
168
|
To run the following examples and see the CSS they produce,
|
169
169
|
put them in a file called `test.scss` and run `sass test.scss`.
|
@@ -232,7 +232,7 @@ You can even give them arguments.
|
|
232
232
|
}
|
233
233
|
|
234
234
|
A comprehensive list of features is available
|
235
|
-
in the [Sass reference](http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.
|
235
|
+
in the [Sass reference](http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html).
|
236
236
|
|
237
237
|
## Executables
|
238
238
|
|
data/REMEMBER
CHANGED
@@ -7,6 +7,7 @@ Don't conflict with Object#extend.
|
|
7
7
|
http://camendesign.com/design/ provides some interesting formatting and nesting issues for sass-convert
|
8
8
|
Charles Roper's example code for media queries doesn't fare well in css2sass either
|
9
9
|
|
10
|
-
Handle unicode escapes (and other escapes?) gracefully in script idents with sass-convert
|
11
10
|
Add period to SCSS syntax errors?
|
12
11
|
Better #{} in prop names
|
12
|
+
Faster than Less
|
13
|
+
Comma multiline for Haml
|
data/Rakefile
CHANGED
@@ -70,7 +70,7 @@ at_exit { File.delete(scope('REVISION')) rescue nil }
|
|
70
70
|
|
71
71
|
desc "Install Haml as a gem."
|
72
72
|
task :install => [:package] do
|
73
|
-
sudo = RUBY_PLATFORM =~ /win32/ ? '' : 'sudo'
|
73
|
+
sudo = RUBY_PLATFORM =~ /win32|mingw/ ? '' : 'sudo'
|
74
74
|
gem = RUBY_PLATFORM =~ /java/ ? 'jgem' : 'gem'
|
75
75
|
sh %{#{sudo} #{gem} install --no-ri pkg/haml-#{File.read(scope('VERSION')).strip}}
|
76
76
|
end
|
@@ -191,14 +191,16 @@ task :release_edge do
|
|
191
191
|
sh %{git merge origin/master}
|
192
192
|
|
193
193
|
# Get the current master branch version
|
194
|
-
version = File.read(scope('VERSION')).strip.split('.')
|
195
|
-
|
194
|
+
version = File.read(scope('VERSION')).strip.split('.')
|
195
|
+
pr = version[3]
|
196
|
+
version = version.map {|n| n.to_i}
|
197
|
+
unless pr || (version[1] % 2 == 1 && version[2] == 0)
|
196
198
|
raise "#{version.join('.')} is not a development version"
|
197
199
|
end
|
198
200
|
|
199
201
|
# Bump the edge gem version
|
200
202
|
edge_version = File.read(scope('EDGE_GEM_VERSION')).strip.split('.').map {|n| n.to_i}
|
201
|
-
if edge_version[0..1] != version[0..1]
|
203
|
+
if !pr && (edge_version[0..1] != version[0..1])
|
202
204
|
# A new master branch version was released, reset the edge gem version
|
203
205
|
edge_version[0..1] = version[0..1]
|
204
206
|
edge_version[2] = 0
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.0.0.beta.
|
1
|
+
3.0.0.beta.2
|
data/lib/haml/exec.rb
CHANGED
@@ -15,14 +15,11 @@ module Haml
|
|
15
15
|
|
16
16
|
# Parses the command-line arguments and runs the executable.
|
17
17
|
# Calls `Kernel#exit` at the end, so it never returns.
|
18
|
+
#
|
19
|
+
# @see #parse
|
18
20
|
def parse!
|
19
21
|
begin
|
20
|
-
|
21
|
-
@opts.parse!(@args)
|
22
|
-
|
23
|
-
process_result
|
24
|
-
|
25
|
-
@options
|
22
|
+
parse
|
26
23
|
rescue Exception => e
|
27
24
|
raise e if @options[:trace] || e.is_a?(SystemExit)
|
28
25
|
|
@@ -32,6 +29,19 @@ module Haml
|
|
32
29
|
exit 0
|
33
30
|
end
|
34
31
|
|
32
|
+
# Parses the command-line arguments and runs the executable.
|
33
|
+
# This does not handle exceptions or exit the program.
|
34
|
+
#
|
35
|
+
# @see #parse!
|
36
|
+
def parse
|
37
|
+
@opts = OptionParser.new(&method(:set_opts))
|
38
|
+
@opts.parse!(@args)
|
39
|
+
|
40
|
+
process_result
|
41
|
+
|
42
|
+
@options
|
43
|
+
end
|
44
|
+
|
35
45
|
# @return [String] A description of the executable
|
36
46
|
def to_s
|
37
47
|
@opts.to_s
|
@@ -105,6 +115,39 @@ module Haml
|
|
105
115
|
@options[:input], @options[:output] = input, output
|
106
116
|
end
|
107
117
|
|
118
|
+
# @private
|
119
|
+
COLORS = { :red => 31, :green => 32, :yellow => 33 }
|
120
|
+
|
121
|
+
# Prints a status message about performing the given action,
|
122
|
+
# colored using the given color (via terminal escapes) if possible.
|
123
|
+
#
|
124
|
+
# @param name [#to_s] A short name for the action being performed.
|
125
|
+
# Shouldn't be longer than 11 characters.
|
126
|
+
# @param color [Symbol] The name of the color to use for this action.
|
127
|
+
# Can be `:red`, `:green`, or `:yellow`.
|
128
|
+
def puts_action(name, color, arg)
|
129
|
+
printf color(color, "%11s %s\n"), name, arg
|
130
|
+
end
|
131
|
+
|
132
|
+
# Wraps the given string in terminal escapes
|
133
|
+
# causing it to have the given color.
|
134
|
+
# If terminal esapes aren't supported on this platform,
|
135
|
+
# just returns the string instead.
|
136
|
+
#
|
137
|
+
# @param color [Symbol] The name of the color to use.
|
138
|
+
# Can be `:red`, `:green`, or `:yellow`.
|
139
|
+
# @param str [String] The string to wrap in the given color.
|
140
|
+
# @return [String] The wrapped string.
|
141
|
+
def color(color, str)
|
142
|
+
raise "[BUG] Unrecognized color #{color}" unless COLORS[color]
|
143
|
+
|
144
|
+
# Almost any real Unix terminal will support color,
|
145
|
+
# so we just filter for Windows terms (which don't set TERM)
|
146
|
+
# and not-real terminals, which aren't ttys.
|
147
|
+
return str if ENV["TERM"].nil? || ENV["TERM"].empty? || !STDOUT.tty?
|
148
|
+
return "\e[#{COLORS[color]}m#{str}\e[0m"
|
149
|
+
end
|
150
|
+
|
108
151
|
private
|
109
152
|
|
110
153
|
def open_file(filename, flag = 'r')
|
@@ -233,6 +276,9 @@ END
|
|
233
276
|
'Output style. Can be nested (default), compact, compressed, or expanded.') do |name|
|
234
277
|
@options[:for_engine][:style] = name.to_sym
|
235
278
|
end
|
279
|
+
opts.on('-q', '--quiet', 'Silence warnings during compilation.') do
|
280
|
+
@options[:for_engine][:quiet] = true
|
281
|
+
end
|
236
282
|
opts.on('-g', '--debug-info',
|
237
283
|
'Emit extra information in the generated CSS that can be used by the FireSass Firebug plugin.') do
|
238
284
|
@options[:for_engine][:debug_info] = true
|
@@ -358,23 +404,6 @@ MSG
|
|
358
404
|
|
359
405
|
::Sass::Plugin.watch(files)
|
360
406
|
end
|
361
|
-
|
362
|
-
# @private
|
363
|
-
COLORS = { :red => 31, :green => 32, :yellow => 33 }
|
364
|
-
|
365
|
-
def puts_action(name, color, arg)
|
366
|
-
printf color(color, "%11s %s\n"), name, arg
|
367
|
-
end
|
368
|
-
|
369
|
-
def color(color, str)
|
370
|
-
raise "[BUG] Unrecognized color #{color}" unless COLORS[color]
|
371
|
-
|
372
|
-
# Almost any real Unix terminal will support color,
|
373
|
-
# so we just filter for Windows terms (which don't set TERM)
|
374
|
-
# and not-real terminals, which aren't ttys.
|
375
|
-
return str if ENV["TERM"].empty? || !STDOUT.tty?
|
376
|
-
return "\e[#{COLORS[color]}m#{str}\e[0m"
|
377
|
-
end
|
378
407
|
end
|
379
408
|
|
380
409
|
# The `haml` executable.
|
@@ -565,6 +594,9 @@ END
|
|
565
594
|
'By default, this is inferred from the input filename.',
|
566
595
|
'If there is none, defaults to css.') do |name|
|
567
596
|
@options[:from] = name.downcase.to_sym
|
597
|
+
unless [:css, :scss, :sass, :sass2].include?(@options[:from])
|
598
|
+
raise "Unknown format for sass-convert --from: #{name}"
|
599
|
+
end
|
568
600
|
end
|
569
601
|
|
570
602
|
opts.on('-T', '--to FORMAT',
|
@@ -572,6 +604,14 @@ END
|
|
572
604
|
'By default, this is inferred from the output filename.',
|
573
605
|
'If there is none, defaults to sass.') do |name|
|
574
606
|
@options[:to] = name.downcase.to_sym
|
607
|
+
unless [:scss, :sass].include?(@options[:to])
|
608
|
+
raise "Unknown format for sass-convert --to: #{name}"
|
609
|
+
end
|
610
|
+
end
|
611
|
+
|
612
|
+
opts.on('-R', '--recursive',
|
613
|
+
'Convert all the files in a directory. Requires --from and --to.') do
|
614
|
+
@options[:recursive] = true
|
575
615
|
end
|
576
616
|
|
577
617
|
opts.on('-i', '--in-place',
|
@@ -580,6 +620,10 @@ END
|
|
580
620
|
@options[:in_place] = true
|
581
621
|
end
|
582
622
|
|
623
|
+
opts.on('--dasherize', 'Convert underscores to dashes') do
|
624
|
+
@options[:for_tree][:dasherize] = true
|
625
|
+
end
|
626
|
+
|
583
627
|
opts.on('--old', 'Output the old-style ":prop val" property syntax.',
|
584
628
|
'Only meaningful when generating Sass.') do
|
585
629
|
@options[:for_tree][:old] = true
|
@@ -596,12 +640,63 @@ END
|
|
596
640
|
# and runs the CSS compiler appropriately.
|
597
641
|
def process_result
|
598
642
|
require 'sass'
|
599
|
-
super
|
600
643
|
|
644
|
+
if @options[:recursive]
|
645
|
+
process_directory
|
646
|
+
return
|
647
|
+
end
|
648
|
+
|
649
|
+
super
|
601
650
|
input = @options[:input]
|
651
|
+
raise "Error: '#{input}' is a directory (did you mean to use --recursive?)" if File.directory?(input)
|
602
652
|
output = @options[:output]
|
603
653
|
output = input if @options[:in_place]
|
654
|
+
process_file(input, output)
|
655
|
+
end
|
656
|
+
|
657
|
+
def process_directory
|
658
|
+
input = @options[:input] = @args.shift
|
659
|
+
output = @options[:output] = @args.shift
|
660
|
+
raise "Error: --from required when using --recursive." unless @options[:from]
|
661
|
+
raise "Error: --to required when using --recursive." unless @options[:to]
|
662
|
+
raise "Error: '#{@options[:input]}' is not a directory" unless File.directory?(@options[:input])
|
663
|
+
if @options[:output] && File.exists?(@options[:output]) && !File.directory?(@options[:output])
|
664
|
+
raise "Error: '#{@options[:output]}' is not a directory"
|
665
|
+
end
|
666
|
+
@options[:output] ||= @options[:input]
|
667
|
+
|
668
|
+
ext = @options[:from]
|
669
|
+
ext = :sass if ext == :sass2
|
670
|
+
Dir.glob("#{@options[:input]}/**/*.#{ext}") do |f|
|
671
|
+
output =
|
672
|
+
if @options[:in_place]
|
673
|
+
f
|
674
|
+
elsif @options[:output]
|
675
|
+
output_name = f.gsub(/\.(c|sa|sc)ss$/, ".#{@options[:to]}")
|
676
|
+
output_name[0...@options[:input].size] = @options[:output]
|
677
|
+
output_name
|
678
|
+
else
|
679
|
+
f.gsub(/\.(c|sa|sc)ss$/, ".#{@options[:to]}")
|
680
|
+
end
|
681
|
+
|
682
|
+
unless File.directory?(File.dirname(output))
|
683
|
+
puts_action :directory, :green, File.dirname(output)
|
684
|
+
FileUtils.mkdir_p(File.dirname(output))
|
685
|
+
end
|
686
|
+
puts_action :convert, :green, f
|
687
|
+
if File.exists?(output)
|
688
|
+
puts_action :overwrite, :yellow, output
|
689
|
+
else
|
690
|
+
puts_action :create, :green, output
|
691
|
+
end
|
692
|
+
|
693
|
+
input = open_file(f)
|
694
|
+
output = @options[:in_place] ? input : open_file(output, "w")
|
695
|
+
process_file(input, output)
|
696
|
+
end
|
697
|
+
end
|
604
698
|
|
699
|
+
def process_file(input, output)
|
605
700
|
if input.is_a?(File)
|
606
701
|
@options[:from] ||=
|
607
702
|
case input.path
|
data/lib/haml/filters.rb
CHANGED
@@ -100,7 +100,11 @@ module Haml
|
|
100
100
|
if contains_interpolation?(text)
|
101
101
|
return if options[:suppress_eval]
|
102
102
|
|
103
|
-
text = unescape_interpolation(text).gsub(
|
103
|
+
text = unescape_interpolation(text).gsub(/(\\+)n/) do |s|
|
104
|
+
escapes = $1.size
|
105
|
+
next s if escapes % 2 == 0
|
106
|
+
("\\" * (escapes - 1)) + "\n"
|
107
|
+
end
|
104
108
|
newline if text.gsub!(/\n"\Z/, "\\n\"")
|
105
109
|
push_script <<RUBY.strip, :escape_html => false
|
106
110
|
find_and_preserve(#{filter.inspect}.render_with_options(#{text}, _hamlout.options))
|
data/lib/haml/helpers.rb
CHANGED
@@ -348,7 +348,9 @@ MESSAGE
|
|
348
348
|
haml_buffer.capture_position = position
|
349
349
|
block.call(*args)
|
350
350
|
|
351
|
-
captured = haml_buffer.buffer.slice!(position..-1)
|
351
|
+
captured = haml_buffer.buffer.slice!(position..-1)
|
352
|
+
return captured if haml_buffer.options[:ugly]
|
353
|
+
captured = captured.split(/^/)
|
352
354
|
|
353
355
|
min_tabs = nil
|
354
356
|
captured.each do |line|
|
@@ -511,7 +513,7 @@ MESSAGE
|
|
511
513
|
# @param text [String] The string to sanitize
|
512
514
|
# @return [String] The sanitized string
|
513
515
|
def html_escape(text)
|
514
|
-
text.to_s.gsub(/[\"><&]/n) {|s| HTML_ESCAPE[s]}
|
516
|
+
Haml::Util.silence_warnings {text.to_s.gsub(/[\"><&]/n) {|s| HTML_ESCAPE[s]}}
|
515
517
|
end
|
516
518
|
|
517
519
|
# Escapes HTML entities in `text`, but without escaping an ampersand
|
@@ -125,9 +125,8 @@ module ActionView
|
|
125
125
|
@template_object.send :is_haml?
|
126
126
|
end
|
127
127
|
|
128
|
-
|
129
|
-
|
130
|
-
alias_method :content_tag, :content_tag_with_haml
|
128
|
+
def content_tag(*args)
|
129
|
+
content_tag_with_haml(*args)
|
131
130
|
end
|
132
131
|
end
|
133
132
|
|
data/lib/haml/precompiler.rb
CHANGED
@@ -905,6 +905,7 @@ END
|
|
905
905
|
when "strict"; '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
|
906
906
|
when "frameset"; '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">'
|
907
907
|
when "mobile"; '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">'
|
908
|
+
when "rdfa"; '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">'
|
908
909
|
when "basic"; '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">'
|
909
910
|
else '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
|
910
911
|
end
|
data/lib/sass.rb
CHANGED
@@ -15,7 +15,7 @@ module Sass
|
|
15
15
|
extend Haml::Version
|
16
16
|
|
17
17
|
# A string representing the version of Sass.
|
18
|
-
# A more fine-grained representation is available from {Sass.version}.
|
18
|
+
# A more fine-grained representation is available from {Haml::Version#version Sass.version}.
|
19
19
|
VERSION = version[:string] unless defined?(Sass::VERSION)
|
20
20
|
end
|
21
21
|
|
data/lib/sass/css.rb
CHANGED
@@ -79,7 +79,10 @@ module Sass
|
|
79
79
|
# @param root [Tree::Node] The parent node
|
80
80
|
def expand_commas(root)
|
81
81
|
root.children.map! do |child|
|
82
|
-
|
82
|
+
unless child.is_a?(Tree::RuleNode) && child.rule.first.include?(',')
|
83
|
+
expand_commas(child) if child.is_a?(Tree::DirectiveNode)
|
84
|
+
next child
|
85
|
+
end
|
83
86
|
child.rule.first.split(',').map do |rule|
|
84
87
|
node = Tree::RuleNode.new([rule.strip])
|
85
88
|
node.children = child.children
|
@@ -126,9 +129,12 @@ module Sass
|
|
126
129
|
def parent_ref_rules(root)
|
127
130
|
current_rule = nil
|
128
131
|
root.children.map! do |child|
|
129
|
-
|
132
|
+
unless child.is_a?(Tree::RuleNode)
|
133
|
+
parent_ref_rules(child) if child.is_a?(Tree::DirectiveNode)
|
134
|
+
next child
|
135
|
+
end
|
130
136
|
|
131
|
-
first, rest = child.rule.first.scan(
|
137
|
+
first, rest = child.rule.first.scan(/\A(&?(?: .|[^ ])[^.#: \[]*)([.#: \[].*)?\Z/m).first
|
132
138
|
|
133
139
|
if current_rule.nil? || current_rule.rule.first != first
|
134
140
|
current_rule = Tree::RuleNode.new([first])
|
@@ -164,9 +170,12 @@ module Sass
|
|
164
170
|
# @param root [Tree::Node] The parent node
|
165
171
|
def remove_parent_refs(root)
|
166
172
|
root.children.each do |child|
|
167
|
-
|
173
|
+
case child
|
174
|
+
when Tree::RuleNode
|
168
175
|
child.rule.first.gsub! /^& +/, ''
|
169
176
|
remove_parent_refs child
|
177
|
+
when Tree::DirectiveNode
|
178
|
+
remove_parent_refs child
|
170
179
|
end
|
171
180
|
end
|
172
181
|
end
|
@@ -195,7 +204,14 @@ module Sass
|
|
195
204
|
#
|
196
205
|
# @param root [Tree::Node] The parent node
|
197
206
|
def flatten_rules(root)
|
198
|
-
root.children.each
|
207
|
+
root.children.each do |child|
|
208
|
+
case child
|
209
|
+
when Tree::RuleNode
|
210
|
+
flatten_rule(child)
|
211
|
+
when Tree::DirectiveNode
|
212
|
+
flatten_rules(child)
|
213
|
+
end
|
214
|
+
end
|
199
215
|
end
|
200
216
|
|
201
217
|
# Flattens a single rule
|
@@ -236,7 +252,10 @@ module Sass
|
|
236
252
|
def fold_commas(root)
|
237
253
|
prev_rule = nil
|
238
254
|
root.children.map! do |child|
|
239
|
-
|
255
|
+
unless child.is_a?(Tree::RuleNode)
|
256
|
+
fold_commas(child) if child.is_a?(Tree::DirectiveNode)
|
257
|
+
next child
|
258
|
+
end
|
240
259
|
|
241
260
|
if prev_rule && prev_rule.children == child.children
|
242
261
|
prev_rule.rule.first << ", #{child.rule.first}"
|
data/lib/sass/engine.rb
CHANGED
@@ -13,6 +13,7 @@ require 'sass/tree/if_node'
|
|
13
13
|
require 'sass/tree/while_node'
|
14
14
|
require 'sass/tree/for_node'
|
15
15
|
require 'sass/tree/debug_node'
|
16
|
+
require 'sass/tree/warn_node'
|
16
17
|
require 'sass/tree/import_node'
|
17
18
|
require 'sass/environment'
|
18
19
|
require 'sass/script'
|
@@ -164,9 +165,9 @@ module Sass
|
|
164
165
|
# @return [String] The CSS
|
165
166
|
# @raise [Sass::SyntaxError] if there's an error in the document
|
166
167
|
def render
|
167
|
-
|
168
|
+
return _to_tree.render unless @options[:quiet]
|
169
|
+
Haml::Util.silence_haml_warnings {_to_tree.render}
|
168
170
|
end
|
169
|
-
|
170
171
|
alias_method :to_css, :render
|
171
172
|
|
172
173
|
# Parses the document into its parse tree.
|
@@ -174,6 +175,13 @@ module Sass
|
|
174
175
|
# @return [Sass::Tree::Node] The root of the parse tree.
|
175
176
|
# @raise [Sass::SyntaxError] if there's an error in the document
|
176
177
|
def to_tree
|
178
|
+
return _to_tree unless @options[:quiet]
|
179
|
+
Haml::Util.silence_haml_warnings {_to_tree}
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def _to_tree
|
177
185
|
@template = check_encoding(@template) {|msg, line| raise Sass::SyntaxError.new(msg, :line => line)}
|
178
186
|
|
179
187
|
if @options[:syntax] == :scss
|
@@ -191,8 +199,6 @@ module Sass
|
|
191
199
|
raise e
|
192
200
|
end
|
193
201
|
|
194
|
-
private
|
195
|
-
|
196
202
|
def tabulate(string)
|
197
203
|
tab_str = nil
|
198
204
|
comment_tab_str = nil
|
@@ -415,7 +421,7 @@ WARNING
|
|
415
421
|
if eq.strip[0] == SCRIPT_CHAR
|
416
422
|
expr.context = :equals
|
417
423
|
Script.equals_warning("properties", name,
|
418
|
-
Sass::Tree::PropNode.val_to_sass(expr), false,
|
424
|
+
Sass::Tree::PropNode.val_to_sass(expr, @options), false,
|
419
425
|
@line, line.offset + 1, @options[:filename])
|
420
426
|
end
|
421
427
|
end
|
@@ -461,10 +467,13 @@ WARNING
|
|
461
467
|
|
462
468
|
# If value begins with url( or ",
|
463
469
|
# it's a CSS @import rule and we don't want to touch it.
|
464
|
-
if directive == "import" && value !~ /^(url\(|")/
|
470
|
+
if directive == "import" && value !~ /^(url\(|["'])/
|
465
471
|
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath import directives.",
|
466
472
|
:line => @line + 1) unless line.children.empty?
|
467
|
-
value.split(/,\s*/).map
|
473
|
+
value.split(/,\s*/).map do |f|
|
474
|
+
f = $1 || $2 || $3 if f =~ Sass::SCSS::RX::STRING || f =~ Sass::SCSS::RX::URI
|
475
|
+
Tree::ImportNode.new(f)
|
476
|
+
end
|
468
477
|
elsif directive == "mixin"
|
469
478
|
parse_mixin_definition(line)
|
470
479
|
elsif directive == "include"
|
@@ -485,6 +494,12 @@ WARNING
|
|
485
494
|
:line => @line + 1) unless line.children.empty?
|
486
495
|
offset = line.offset + line.text.index(value).to_i
|
487
496
|
Tree::DebugNode.new(parse_script(value, :offset => offset))
|
497
|
+
elsif directive == "warn"
|
498
|
+
raise SyntaxError.new("Invalid warn directive '@warn': expected expression.") unless value
|
499
|
+
raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath warn directives.",
|
500
|
+
:line => @line + 1) unless line.children.empty?
|
501
|
+
offset = line.offset + line.text.index(value).to_i
|
502
|
+
Tree::WarnNode.new(parse_script(value, :offset => offset))
|
488
503
|
else
|
489
504
|
Tree::DirectiveNode.new(line.text)
|
490
505
|
end
|
@@ -573,6 +588,7 @@ WARNING
|
|
573
588
|
end
|
574
589
|
|
575
590
|
return silent ? "//" : "/* */" if content.empty?
|
591
|
+
content.each {|l| l.gsub!(/^\* /, '')}
|
576
592
|
content.map! {|l| (l.empty? ? "" : " ") + l}
|
577
593
|
content.first.gsub!(/^ /, '') unless removed_first
|
578
594
|
content.last.gsub!(%r{ ?\*/ *$}, '')
|