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.

Files changed (67) hide show
  1. data/README.md +7 -7
  2. data/REMEMBER +2 -1
  3. data/Rakefile +6 -4
  4. data/VERSION +1 -1
  5. data/lib/haml/exec.rb +119 -24
  6. data/lib/haml/filters.rb +5 -1
  7. data/lib/haml/helpers.rb +4 -2
  8. data/lib/haml/helpers/action_view_mods.rb +2 -3
  9. data/lib/haml/precompiler.rb +1 -0
  10. data/lib/sass.rb +1 -1
  11. data/lib/sass/css.rb +25 -6
  12. data/lib/sass/engine.rb +23 -7
  13. data/lib/sass/environment.rb +47 -1
  14. data/lib/sass/files.rb +9 -10
  15. data/lib/sass/plugin.rb +6 -27
  16. data/lib/sass/plugin/merb.rb +1 -0
  17. data/lib/sass/plugin/rails.rb +1 -0
  18. data/lib/sass/plugin/staleness_checker.rb +123 -0
  19. data/lib/sass/script/bool.rb +1 -1
  20. data/lib/sass/script/color.rb +1 -1
  21. data/lib/sass/script/css_lexer.rb +1 -4
  22. data/lib/sass/script/funcall.rb +2 -2
  23. data/lib/sass/script/functions.rb +102 -7
  24. data/lib/sass/script/interpolation.rb +5 -5
  25. data/lib/sass/script/lexer.rb +10 -8
  26. data/lib/sass/script/literal.rb +11 -1
  27. data/lib/sass/script/node.rb +10 -1
  28. data/lib/sass/script/number.rb +25 -10
  29. data/lib/sass/script/operation.rb +7 -6
  30. data/lib/sass/script/parser.rb +37 -28
  31. data/lib/sass/script/string.rb +12 -7
  32. data/lib/sass/script/string_interpolation.rb +70 -0
  33. data/lib/sass/script/unary_operation.rb +3 -3
  34. data/lib/sass/script/variable.rb +2 -2
  35. data/lib/sass/scss/css_parser.rb +1 -0
  36. data/lib/sass/scss/parser.rb +58 -44
  37. data/lib/sass/scss/rx.rb +1 -0
  38. data/lib/sass/tree/comment_node.rb +3 -2
  39. data/lib/sass/tree/debug_node.rb +1 -1
  40. data/lib/sass/tree/for_node.rb +1 -1
  41. data/lib/sass/tree/if_node.rb +1 -1
  42. data/lib/sass/tree/import_node.rb +3 -0
  43. data/lib/sass/tree/mixin_def_node.rb +3 -3
  44. data/lib/sass/tree/mixin_node.rb +7 -3
  45. data/lib/sass/tree/node.rb +8 -0
  46. data/lib/sass/tree/prop_node.rb +21 -16
  47. data/lib/sass/tree/rule_node.rb +3 -3
  48. data/lib/sass/tree/variable_node.rb +1 -1
  49. data/lib/sass/tree/warn_node.rb +41 -0
  50. data/lib/sass/tree/while_node.rb +1 -1
  51. data/test/haml/engine_test.rb +9 -0
  52. data/test/sass/conversion_test.rb +127 -15
  53. data/test/sass/css2sass_test.rb +34 -3
  54. data/test/sass/engine_test.rb +82 -5
  55. data/test/sass/functions_test.rb +31 -0
  56. data/test/sass/plugin_test.rb +25 -24
  57. data/test/sass/results/script.css +4 -4
  58. data/test/sass/results/warn.css +0 -0
  59. data/test/sass/results/warn_imported.css +0 -0
  60. data/test/sass/script_conversion_test.rb +43 -1
  61. data/test/sass/script_test.rb +3 -3
  62. data/test/sass/scss/css_test.rb +46 -5
  63. data/test/sass/scss/scss_test.rb +72 -0
  64. data/test/sass/templates/import.sass +1 -1
  65. data/test/sass/templates/warn.sass +3 -0
  66. data/test/sass/templates/warn_imported.sass +4 -0
  67. metadata +10 -3
@@ -17,7 +17,7 @@ module Sass
17
17
  protected
18
18
 
19
19
  def to_src(tabs, opts, fmt)
20
- "#{' ' * tabs}$#{@name}: #{@expr.to_sass}#{' !default' if @guarded}#{semi fmt}\n"
20
+ "#{' ' * tabs}$#{dasherize(@name, opts)}: #{@expr.to_sass(opts)}#{' !default' if @guarded}#{semi fmt}\n"
21
21
  end
22
22
 
23
23
  # Loads the new variable value into the environment.
@@ -0,0 +1,41 @@
1
+ module Sass
2
+ module Tree
3
+ # A dynamic node representing a Sass `@warn` statement.
4
+ #
5
+ # @see Sass::Tree
6
+ class WarnNode < Node
7
+ # @param expr [Script::Node] The expression to print
8
+ def initialize(expr)
9
+ @expr = expr
10
+ super()
11
+ end
12
+
13
+ protected
14
+
15
+ def to_src(tabs, opts, fmt)
16
+ "#{' ' * tabs}@warn #{@expr.to_sass(opts)}#{semi fmt}\n"
17
+ end
18
+
19
+ # Prints the expression to STDERR with a stylesheet trace.
20
+ #
21
+ # @param environment [Sass::Environment] The lexical environment containing
22
+ # variable and mixin values
23
+ def _perform(environment)
24
+ environment.push_frame(:filename => filename, :line => line)
25
+ res = @expr.perform(environment)
26
+ res = res.value if res.is_a?(Sass::Script::String)
27
+ msg = "WARNING: #{res}\n"
28
+ environment.stack.reverse.each_with_index do |entry, i|
29
+ msg << " #{i == 0 ? "on" : "from"} line #{entry[:line]}" <<
30
+ " of #{entry[:filename] || "an unknown file"}"
31
+ msg << ", in `#{entry[:mixin]}'" if entry[:mixin]
32
+ msg << "\n"
33
+ end
34
+ Haml::Util.haml_warn msg
35
+ []
36
+ ensure
37
+ environment.pop_frame
38
+ end
39
+ end
40
+ end
41
+ end
@@ -14,7 +14,7 @@ module Sass::Tree
14
14
  protected
15
15
 
16
16
  def to_src(tabs, opts, fmt)
17
- "#{' ' * tabs}@while #{@expr.to_sass}" + children_to_src(tabs, opts, fmt)
17
+ "#{' ' * tabs}@while #{@expr.to_sass(opts)}" + children_to_src(tabs, opts, fmt)
18
18
  end
19
19
 
20
20
  # Runs the child nodes until the continue expression becomes false.
@@ -671,6 +671,15 @@ HAML
671
671
  assert_equal("<a href='#\"'></a>\n", render('%a(href="#\\"")'))
672
672
  end
673
673
 
674
+ def test_filter_with_newline_and_interp
675
+ assert_equal(<<HTML, render(<<HAML))
676
+ \\n
677
+ HTML
678
+ :plain
679
+ \\n\#{""}
680
+ HAML
681
+ end
682
+
674
683
  # HTML escaping tests
675
684
 
676
685
  def test_ampersand_equals_should_escape
@@ -251,9 +251,9 @@ SCSS
251
251
 
252
252
  assert_renders <<SASS, <<SCSS
253
253
  // foo
254
- bar
255
- baz
256
- bang
254
+ // bar
255
+ // baz
256
+ // bang
257
257
 
258
258
  foo bar
259
259
  a: b
@@ -309,9 +309,9 @@ SCSS
309
309
 
310
310
  assert_scss_to_sass <<SASS, <<SCSS
311
311
  /* foo
312
- bar
313
- baz
314
- bang
312
+ * bar
313
+ * baz
314
+ * bang
315
315
 
316
316
  foo bar
317
317
  a: b
@@ -337,9 +337,9 @@ SCSS
337
337
 
338
338
  assert_renders <<SASS, <<SCSS
339
339
  /* foo
340
- bar
341
- baz
342
- bang
340
+ * bar
341
+ * baz
342
+ * bang
343
343
 
344
344
  foo bar
345
345
  a: b
@@ -358,8 +358,8 @@ SCSS
358
358
  assert_scss_to_sass <<SASS, <<SCSS
359
359
  foo
360
360
  /* foo
361
- bar
362
- baz
361
+ * bar
362
+ * baz
363
363
  a: b
364
364
  SASS
365
365
  foo {
@@ -387,8 +387,8 @@ SASS
387
387
  def test_immediately_preceding_comments
388
388
  assert_renders <<SASS, <<SCSS
389
389
  /* Foo
390
- Bar
391
- Baz
390
+ * Bar
391
+ * Baz
392
392
  .foo#bar
393
393
  a: b
394
394
  SASS
@@ -401,8 +401,8 @@ SCSS
401
401
 
402
402
  assert_renders <<SASS, <<SCSS
403
403
  // Foo
404
- Bar
405
- Baz
404
+ // Bar
405
+ // Baz
406
406
  =foo
407
407
  a: b
408
408
  SASS
@@ -777,6 +777,71 @@ SCSS
777
777
  assert_sass_to_scss '$var: 12px $bar baz !default;', '$var ||= 12px $bar "baz"'
778
778
  end
779
779
 
780
+ # Hacks
781
+
782
+ def test_declaration_hacks
783
+ assert_renders <<SASS, <<SCSS
784
+ foo
785
+ _name: val
786
+ *name: val
787
+ #name: val
788
+ .name: val
789
+ name: val
790
+ SASS
791
+ foo {
792
+ _name: val;
793
+ *name: val;
794
+ #name: val;
795
+ .name: val;
796
+ name: val; }
797
+ SCSS
798
+ end
799
+
800
+ def test_old_declaration_hacks
801
+ assert_renders <<SASS, <<SCSS, :old => true
802
+ foo
803
+ :_name val
804
+ :*name val
805
+ :#name val
806
+ :.name val
807
+ :name val
808
+ SASS
809
+ foo {
810
+ _name: val;
811
+ *name: val;
812
+ #name: val;
813
+ .name: val;
814
+ name: val; }
815
+ SCSS
816
+ end
817
+
818
+ def test_selector_hacks
819
+ assert_selector_renders = lambda do |s|
820
+ assert_renders <<SASS, <<SCSS
821
+ #{s}
822
+ a: b
823
+ SASS
824
+ #{s} {
825
+ a: b; }
826
+ SCSS
827
+ end
828
+
829
+ assert_selector_renders['> E']
830
+ assert_selector_renders['+ E']
831
+ assert_selector_renders['~ E']
832
+ assert_selector_renders['>> E']
833
+
834
+ assert_selector_renders['E*']
835
+ assert_selector_renders['E*.foo']
836
+ assert_selector_renders['E*:hover']
837
+ end
838
+
839
+ def test_disallowed_colon_hack
840
+ assert_raise(Sass::SyntaxError, '":foo: bar" is not allowed in the Sass syntax') do
841
+ to_sass("foo {:name: val;}", :syntax => :scss)
842
+ end
843
+ end
844
+
780
845
  # Sass 3 Deprecation conversions
781
846
 
782
847
  def test_simple_quoted_strings_unquoted_with_equals
@@ -833,6 +898,53 @@ foo
833
898
  SASS
834
899
  end
835
900
 
901
+ def test_nested_properties
902
+ assert_renders <<SASS, <<SCSS
903
+ div
904
+ before: before
905
+ background:
906
+ color: blue
907
+ repeat: no-repeat
908
+ after: after
909
+ SASS
910
+ div {
911
+ before: before;
912
+ background: {
913
+ color: blue;
914
+ repeat: no-repeat; };
915
+ after: after; }
916
+
917
+ SCSS
918
+ end
919
+
920
+ def test_dasherize
921
+ assert_sass_to_scss(<<SCSS, <<SASS, :dasherize => true)
922
+ @mixin under-scored-mixin($under-scored-arg: $under-scored-default) {
923
+ bar: $under-scored-arg; }
924
+
925
+ div {
926
+ foo: under-scored-fn($under-scored-var + "before\#{$another-under-scored-var}after");
927
+ @include under-scored-mixin($passed-arg);
928
+ selector-\#{$under-scored-interp}: bold; }
929
+
930
+ @if $under-scored {
931
+ @for $for-var from $from-var to $to-var {
932
+ @while $while-var == true {
933
+ $while-var: false; } } }
934
+ SCSS
935
+ =under_scored_mixin($under_scored_arg: $under_scored_default)
936
+ bar: $under_scored_arg
937
+ div
938
+ foo: under_scored_fn($under_scored_var + "before\#{$another_under_scored_var}after")
939
+ +under_scored_mixin($passed_arg)
940
+ selector-\#{$under_scored_interp}: bold
941
+ @if $under_scored
942
+ @for $for_var from $from_var to $to_var
943
+ @while $while_var == true
944
+ $while_var : false
945
+ SASS
946
+ end
947
+
836
948
  private
837
949
 
838
950
  def assert_sass_to_sass(sass, options = {})
@@ -105,20 +105,20 @@ elephant.rawr
105
105
  rampages: excessively
106
106
 
107
107
  /* actual multiline
108
- comment
108
+ *comment
109
109
 
110
110
  span.turkey
111
111
  isdinner: true
112
112
 
113
113
  .turducken
114
114
  /* Sounds funny
115
- doesn't it
115
+ * doesn't it
116
116
  chimera: not_really
117
117
 
118
118
  #overhere
119
119
  bored: sorta
120
120
  /* it's for a good
121
- cause
121
+ * cause
122
122
  better_than: thread_pools
123
123
 
124
124
  #one_more
@@ -237,6 +237,37 @@ SASS
237
237
  CSS
238
238
  end
239
239
 
240
+ # Regressions
241
+
242
+ def test_nesting_within_media
243
+ assert_equal(<<SASS, css2sass(<<CSS))
244
+ @media all
245
+ .next .vevent
246
+ padding-left: 0
247
+ padding-right: 0
248
+ SASS
249
+ @media all {
250
+ .next .vevent {
251
+ padding-left: 0;
252
+ padding-right: 0; } }
253
+ CSS
254
+ end
255
+
256
+ def test_multiline_selector_within_media_and_with_child_selector
257
+ assert_equal(<<SASS, css2sass(<<CSS))
258
+ @media all
259
+ foo bar, baz
260
+ padding-left: 0
261
+ padding-right: 0
262
+ SASS
263
+ @media all {
264
+ foo bar,
265
+ baz {
266
+ padding-left: 0;
267
+ padding-right: 0; } }
268
+ CSS
269
+ end
270
+
240
271
  # Error reporting
241
272
 
242
273
  def test_error_reporting
@@ -81,10 +81,10 @@ MSG
81
81
  "a\n b: c\na\n d: e" => ["The line was indented 2 levels deeper than the previous line.", 4],
82
82
  "a\n b: c\n a\n d: e" => ["The line was indented 3 levels deeper than the previous line.", 4],
83
83
  "a\n \tb: c" => ["Indentation can't use both tabs and spaces.", 2],
84
- "=a(" => 'Invalid CSS after "(": expected ")", was ""',
85
- "=a(b)" => 'Invalid CSS after "(": expected ")", was "b)"',
86
- "=a(,)" => 'Invalid CSS after "(": expected ")", was ",)"',
87
- "=a(!)" => 'Invalid CSS after "(": expected ")", was "!)"',
84
+ "=a(" => 'Invalid CSS after "(": expected variable (e.g. $foo), was ""',
85
+ "=a(b)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was "b)"',
86
+ "=a(,)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was ",)"',
87
+ "=a($)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was "$)"',
88
88
  "=a($foo bar)" => 'Invalid CSS after "($foo ": expected ")", was "bar)"',
89
89
  "=foo\n bar: baz\n+foo" => ["Properties aren't allowed at the root of a document.", 2],
90
90
  "a-\#{$b\n c: d" => ['Invalid CSS after "a-#{$b": expected "}", was ""', 1],
@@ -107,6 +107,9 @@ MSG
107
107
  '@if' => "Invalid if directive '@if': expected expression.",
108
108
  '@while' => "Invalid while directive '@while': expected expression.",
109
109
  '@debug' => "Invalid debug directive '@debug': expected expression.",
110
+ %Q{@debug "a message"\n "nested message"} => "Illegal nesting: Nothing may be nested beneath debug directives.",
111
+ '@warn' => "Invalid warn directive '@warn': expected expression.",
112
+ %Q{@warn "a message"\n "nested message"} => "Illegal nesting: Nothing may be nested beneath warn directives.",
110
113
  "/* foo\n bar\n baz" => "Inconsistent indentation: previous line was indented by 4 spaces, but this line was indented by 2 spaces.",
111
114
 
112
115
  # Regression tests
@@ -937,7 +940,7 @@ SASS
937
940
  def test_equals_warning_for_mixin_args
938
941
  assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SASS))}
939
942
  DEPRECATION WARNING:
940
- On line 1, character 6 of 'test_equals_warning_for_mixin_args_inline.sass'
943
+ On line 1, character 10 of 'test_equals_warning_for_mixin_args_inline.sass'
941
944
  Setting mixin argument defaults with = has been deprecated and will be removed in version 3.2.
942
945
  Use "$arg: 1px" instead.
943
946
 
@@ -1301,6 +1304,18 @@ foo {
1301
1304
  CSS
1302
1305
  end
1303
1306
 
1307
+ def test_loud_comments_with_starred_lines
1308
+ assert_equal(<<CSS, render(<<SASS))
1309
+ /* This is a comment that
1310
+ * continues to the second line.
1311
+ * And even to the third! */
1312
+ CSS
1313
+ /* This is a comment that
1314
+ * continues to the second line.
1315
+ * And even to the third!
1316
+ SASS
1317
+ end
1318
+
1304
1319
  def test_comment_indentation_at_beginning_of_doc
1305
1320
  assert_equal <<CSS, render(<<SASS)
1306
1321
  /* foo
@@ -1709,6 +1724,58 @@ SASS
1709
1724
  end
1710
1725
  end
1711
1726
 
1727
+ def test_warn_directive
1728
+ expected_warning = <<EXPECTATION
1729
+ WARNING: this is a warning
1730
+ on line 4 of test_warn_directive_inline.sass
1731
+
1732
+ WARNING: this is a mixin warning
1733
+ on line 2 of test_warn_directive_inline.sass, in `foo'
1734
+ from line 7 of test_warn_directive_inline.sass
1735
+ EXPECTATION
1736
+ assert_warning expected_warning do
1737
+ assert_equal <<CSS, render(<<SASS)
1738
+ bar {
1739
+ c: d; }
1740
+ CSS
1741
+ =foo
1742
+ @warn "this is a mixin warning"
1743
+
1744
+ @warn "this is a warning"
1745
+ bar
1746
+ c: d
1747
+ +foo
1748
+ SASS
1749
+ end
1750
+ end
1751
+
1752
+ def test_warn_directive_when_quiet
1753
+ assert_warning "" do
1754
+ assert_equal <<CSS, render(<<SASS, :quiet => true)
1755
+ CSS
1756
+ @warn "this is a warning"
1757
+ SASS
1758
+ end
1759
+ end
1760
+
1761
+ def test_warn_with_imports
1762
+ expected_warning = <<WARN
1763
+ WARNING: In the main file
1764
+ on line 1 of #{File.dirname(__FILE__)}/templates/warn.sass
1765
+
1766
+ WARNING: Imported
1767
+ on line 1 of #{File.dirname(__FILE__)}/templates/warn_imported.sass
1768
+ from line 2 of #{File.dirname(__FILE__)}/templates/warn.sass
1769
+
1770
+ WARNING: In an imported mixin
1771
+ on line 4 of #{File.dirname(__FILE__)}/templates/warn_imported.sass, in `emits-a-warning'
1772
+ from line 3 of #{File.dirname(__FILE__)}/templates/warn.sass
1773
+ WARN
1774
+ assert_warning expected_warning do
1775
+ renders_correctly "warn", :style => :compact, :load_paths => [File.dirname(__FILE__) + "/templates"]
1776
+ end
1777
+ end
1778
+
1712
1779
  # Regression tests
1713
1780
 
1714
1781
  def test_parens_in_mixins
@@ -1834,6 +1901,15 @@ a
1834
1901
  SASS
1835
1902
  end
1836
1903
 
1904
+ def test_mixin_no_arg_error
1905
+ assert_raise(Sass::SyntaxError, 'Invalid CSS after "($bar,": expected variable name, was ")"') do
1906
+ render(<<SASS)
1907
+ =foo($bar,)
1908
+ bip: bap
1909
+ SASS
1910
+ end
1911
+ end
1912
+
1837
1913
  # Encodings
1838
1914
 
1839
1915
  unless Haml::Util.ruby1_8?
@@ -1891,3 +1967,4 @@ SASS
1891
1967
  Sass::Files.send(:sassc_filename, sassc_path, Sass::Engine::DEFAULT_OPTIONS)
1892
1968
  end
1893
1969
  end
1970
+