haml 1.7.2 → 1.8.0

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 (71) hide show
  1. data/README +17 -9
  2. data/Rakefile +12 -4
  3. data/VERSION +1 -1
  4. data/init.rb +1 -6
  5. data/lib/haml.rb +65 -7
  6. data/lib/haml/buffer.rb +49 -84
  7. data/lib/haml/engine.rb +155 -797
  8. data/lib/haml/error.rb +3 -33
  9. data/lib/haml/exec.rb +86 -65
  10. data/lib/haml/filters.rb +57 -27
  11. data/lib/haml/helpers.rb +52 -9
  12. data/lib/haml/helpers/action_view_mods.rb +1 -1
  13. data/lib/haml/html.rb +20 -5
  14. data/lib/haml/precompiler.rb +671 -0
  15. data/lib/haml/template.rb +20 -73
  16. data/lib/haml/template/patch.rb +51 -0
  17. data/lib/haml/template/plugin.rb +21 -0
  18. data/lib/sass.rb +78 -3
  19. data/lib/sass/constant.rb +45 -19
  20. data/lib/sass/constant.rb.rej +42 -0
  21. data/lib/sass/constant/string.rb +4 -0
  22. data/lib/sass/css.rb +162 -39
  23. data/lib/sass/engine.rb +38 -14
  24. data/lib/sass/plugin.rb +79 -44
  25. data/lib/sass/tree/attr_node.rb +12 -11
  26. data/lib/sass/tree/comment_node.rb +9 -3
  27. data/lib/sass/tree/directive_node.rb +51 -0
  28. data/lib/sass/tree/node.rb +13 -6
  29. data/lib/sass/tree/rule_node.rb +34 -12
  30. data/test/benchmark.rb +85 -52
  31. data/test/haml/engine_test.rb +172 -84
  32. data/test/haml/helper_test.rb +31 -3
  33. data/test/haml/html2haml_test.rb +60 -0
  34. data/test/haml/markaby/standard.mab +52 -0
  35. data/test/haml/results/eval_suppressed.xhtml +4 -1
  36. data/test/haml/results/helpers.xhtml +15 -4
  37. data/test/haml/results/just_stuff.xhtml +9 -1
  38. data/test/haml/results/standard.xhtml +0 -1
  39. data/test/haml/rhtml/_av_partial_1.rhtml +12 -0
  40. data/test/haml/rhtml/_av_partial_2.rhtml +8 -0
  41. data/test/haml/rhtml/action_view.rhtml +62 -0
  42. data/test/haml/rhtml/standard.rhtml +0 -1
  43. data/test/haml/template_test.rb +41 -21
  44. data/test/haml/templates/_av_partial_1.haml +9 -0
  45. data/test/haml/templates/_av_partial_2.haml +5 -0
  46. data/test/haml/templates/action_view.haml +47 -0
  47. data/test/haml/templates/eval_suppressed.haml +1 -0
  48. data/test/haml/templates/helpers.haml +9 -3
  49. data/test/haml/templates/just_stuff.haml +10 -1
  50. data/test/haml/templates/partials.haml +1 -1
  51. data/test/haml/templates/standard.haml +0 -1
  52. data/test/profile.rb +2 -2
  53. data/test/sass/engine_test.rb +113 -3
  54. data/test/sass/engine_test.rb.rej +18 -0
  55. data/test/sass/plugin_test.rb +34 -11
  56. data/test/sass/results/compact.css +1 -1
  57. data/test/sass/results/complex.css +1 -1
  58. data/test/sass/results/compressed.css +1 -0
  59. data/test/sass/results/constants.css +3 -1
  60. data/test/sass/results/expanded.css +2 -1
  61. data/test/sass/results/import.css +2 -0
  62. data/test/sass/results/nested.css +2 -1
  63. data/test/sass/templates/_partial.sass +2 -0
  64. data/test/sass/templates/compact.sass +2 -0
  65. data/test/sass/templates/complex.sass +1 -0
  66. data/test/sass/templates/compressed.sass +15 -0
  67. data/test/sass/templates/constants.sass +9 -0
  68. data/test/sass/templates/expanded.sass +2 -0
  69. data/test/sass/templates/import.sass +1 -1
  70. data/test/sass/templates/nested.sass +2 -0
  71. metadata +22 -2
@@ -0,0 +1,9 @@
1
+ %h2 This is a pretty complicated partial
2
+ .partial
3
+ %p It has several nested partials,
4
+ %ul
5
+ - 5.times do
6
+ %li
7
+ %strong Partial:
8
+ - @nesting = 5
9
+ = render :partial => 'haml/templates/av_partial_2'
@@ -0,0 +1,5 @@
1
+ - @nesting -= 1
2
+ .partial{:level => @nesting}
3
+ %h3 This is a crazy deep-nested partial.
4
+ %p== Nesting level #{@nesting}
5
+ = render :partial => 'haml/templates/av_partial_2' if @nesting > 0
@@ -0,0 +1,47 @@
1
+ !!!
2
+ %html{html_attrs}
3
+ %head
4
+ %title Hampton Catlin Is Totally Awesome
5
+ %meta{"http-equiv" => "Content-Type", :content => "text/html; charset=utf-8"}
6
+ %body
7
+ %h1
8
+ This is very much like the standard template,
9
+ except that it has some ActionView-specific stuff.
10
+ It's only used for benchmarking.
11
+ .crazy_partials= render :partial => 'haml/templates/av_partial_1'
12
+ / You're In my house now!
13
+ .header
14
+ Yes, ladies and gentileman. He is just that egotistical.
15
+ Fantastic! This should be multi-line output
16
+ The question is if this would translate! Ahah!
17
+ = 1 + 9 + 8 + 2 #numbers should work and this should be ignored
18
+ #body= " Quotes should be loved! Just like people!"
19
+ - 120.times do |number|
20
+ - number
21
+ Wow.|
22
+ %p
23
+ = "Holy cow " + |
24
+ "multiline " + |
25
+ "tags! " + |
26
+ "A pipe (|) even!" |
27
+ = [1, 2, 3].collect { |n| "PipesIgnored|" }
28
+ = [1, 2, 3].collect { |n| |
29
+ n.to_s |
30
+ }.join("|") |
31
+ %div.silent
32
+ - foo = String.new
33
+ - foo << "this"
34
+ - foo << " shouldn't"
35
+ - foo << " evaluate"
36
+ = foo + " but now it should!"
37
+ -# Woah crap a comment!
38
+
39
+ -# That was a line that shouldn't close everything.
40
+ %ul.really.cool
41
+ - ('a'..'f').each do |a|
42
+ %li= a
43
+ #combo.of_divs_with_underscore= @should_eval = "with this text"
44
+ = [ 104, 101, 108, 108, 111 ].map do |byte|
45
+ - byte.chr
46
+ .footer
47
+ %strong.shout= "This is a really long ruby quote. It should be loved and wrapped because its more than 50 characters. This value may change in the future and this test may look stupid. \nSo, I'm just making it *really* long. God, I hope this works"
@@ -2,6 +2,7 @@
2
2
  = "nor me!"
3
3
  - puts "not even me!"
4
4
  %p= "NO!"
5
+ %p~ "UH-UH!"
5
6
  %h1 Me!
6
7
  #foo
7
8
  %p#bar All
@@ -36,11 +36,15 @@ click
36
36
  - concat "foo\n"
37
37
  - buffer.tabulation = 0
38
38
  - def url_for(*stuff); stuff.join(' '); end
39
+ -# The form URLs must be empty
40
+ -# because of a weird bug that causes url_for to misbehave.
39
41
  %p
40
- = form_tag 'hello/world'
41
- - form_tag 'heeheeaform' do
42
+ = form_tag ''
43
+ - form_tag '' do
42
44
  %div= submit_tag 'save'
43
- - form_for :article, @article, :url => 'article_url' do |f|
45
+ - @foo = 'value one'
46
+ = render :partial => './partial'
47
+ - form_for :article, @article, :url => '' do |f|
44
48
  Title:
45
49
  = f.text_field :title
46
50
  Body:
@@ -61,3 +65,5 @@ click
61
65
  - puts "data"
62
66
  - open :td do
63
67
  - puts "more_data"
68
+ - open :hr
69
+ - open :div, ''
@@ -11,6 +11,14 @@
11
11
  == Embedded? #{true}!
12
12
  - embedded = true
13
13
  == Embedded? #{embedded}!
14
+ == Embedded? #{"twice! #{true}"}!
15
+ == Embedded? #{"one"} af"t"er #{"another"}!
16
+ %p== Embedded? false!
17
+ %p== Embedded? #{true}!
18
+ - embedded = true
19
+ %p== Embedded? #{embedded}!
20
+ %p== Embedded? #{"twice! #{true}"}!
21
+ %p== Embedded? #{"one"} af"t"er #{"another"}!
14
22
  .render= render :inline => "%em= 'wow!'", :type => :haml
15
23
  = "stuff followed by whitespace"
16
24
 
@@ -33,7 +41,8 @@
33
41
  -#
34
42
  Nested Haml comment
35
43
  - raise 'dead'
36
- %p{ :class => "" } class attribute shouldn't appear!
44
+ %p{ :class => "" } class attribute should appear!
45
+ %p{ :gorbachev => nil } this attribute shouldn't appear
37
46
  /[if lte IE6] conditional comment!
38
47
  /[if gte IE7]
39
48
  %p Block conditional comment
@@ -1,3 +1,4 @@
1
+ - @foo = 'value one'
1
2
  %p
2
3
  @foo =
3
4
  = @foo
@@ -9,4 +10,3 @@
9
10
  %p
10
11
  @foo =
11
12
  = @foo
12
- - @foo = 'value one'
@@ -5,7 +5,6 @@
5
5
  %meta{"http-equiv" => "Content-Type", :content => "text/html; charset=utf-8"}
6
6
  %body
7
7
  / You're In my house now!
8
- - concat("foo\n")
9
8
  .header
10
9
  Yes, ladies and gentileman. He is just that egotistical.
11
10
  Fantastic! This should be multi-line output
@@ -5,6 +5,7 @@ require 'action_view'
5
5
 
6
6
  require File.dirname(__FILE__) + '/../lib/haml'
7
7
  require 'haml/template'
8
+
8
9
  require 'profiler'
9
10
  require 'stringio'
10
11
 
@@ -35,7 +36,6 @@ module Haml
35
36
  # Creates a new profiler that looks for templates in the base
36
37
  # directory.
37
38
  def initialize(base = File.join(File.dirname(__FILE__), 'haml', 'templates'))
38
- ActionView::Base.register_template_handler("haml", Haml::Template)
39
39
  unless base.class == ActionView::Base
40
40
  @base = ActionView::Base.new(base)
41
41
  else
@@ -48,7 +48,7 @@ module Haml
48
48
  # automatically look for a haml template.
49
49
  #
50
50
  # Returns the results of the profiling as a string.
51
- def profile(runs = 100, template_name = 'standard')
51
+ def profile(runs = 100, template_name = 'standard')
52
52
  AbstractProfiler.profile(runs) { @base.render template_name }
53
53
  end
54
54
  end
@@ -39,11 +39,13 @@ class SassEngineTest < Test::Unit::TestCase
39
39
  "!a = 1b + 2c" => "Incompatible units: b and c",
40
40
  "& a\n :b c" => "Base-level rules cannot contain the parent-selector-referencing character '&'",
41
41
  "a\n :b\n c" => "Illegal nesting: Only attributes may be nested beneath attributes.",
42
+ "a,\n :b c" => "Rules can\'t end in commas.",
42
43
  "!a = b\n :c d\n" => "Illegal nesting: Nothing may be nested beneath constants.",
43
44
  "@import foo.sass" => "File to import not found or unreadable: foo.sass",
44
45
  "@import templates/basic\n foo" => "Illegal nesting: Nothing may be nested beneath import directives.",
45
46
  "foo\n @import templates/basic" => "Import directives may only be used at the root of a document.",
46
- "@foo bar boom" => "Unknown compiler directive: \"@foo bar boom\"",
47
+ "!foo = bar baz !" => "Unterminated constant.",
48
+ "!foo = !(foo)" => "Invalid constant.",
47
49
  }
48
50
 
49
51
  def test_basic_render
@@ -54,6 +56,7 @@ class SassEngineTest < Test::Unit::TestCase
54
56
  renders_correctly "expanded", { :style => :expanded }
55
57
  renders_correctly "compact", { :style => :compact }
56
58
  renders_correctly "nested", { :style => :nested }
59
+ renders_correctly "compressed", { :style => :compressed }
57
60
  end
58
61
 
59
62
  def test_exceptions
@@ -95,12 +98,119 @@ class SassEngineTest < Test::Unit::TestCase
95
98
  end
96
99
  end
97
100
 
98
- def test_empty_first_line
99
- assert_equal("#a {\n b: c; }\n", Sass::Engine.new("#a\n\n b: c").render)
101
+ def test_default_function
102
+ assert_equal("foo {\n bar: url(foo.png); }\n",
103
+ render("foo\n bar = url(foo.png)\n"));
104
+ end
105
+
106
+ def test_multiline_selector
107
+ assert_equal("#foo #bar,\n#baz #boom {\n foo: bar; }\n",
108
+ render("#foo #bar,\n#baz #boom\n :foo bar"))
109
+ assert_equal("#foo #bar,\n#foo #baz {\n foo: bar; }\n",
110
+ render("#foo\n #bar,\n #baz\n :foo bar"))
111
+ assert_equal("#foo #bar, #baz #boom { foo: bar; }\n",
112
+ render("#foo #bar,\n#baz #boom\n :foo bar", :style => :compact))
113
+
114
+ assert_equal("#foo #bar,#baz #boom{foo:bar}\n",
115
+ render("#foo #bar,\n#baz #boom\n :foo bar", :style => :compressed))
116
+ end
117
+
118
+ def test_colon_only
119
+ begin
120
+ render("a\n b: c", :attribute_syntax => :normal)
121
+ rescue Sass::SyntaxError => e
122
+ assert_equal("Illegal attribute syntax: can't use alternate syntax when :attribute_syntax => :normal is set.",
123
+ e.message)
124
+ else
125
+ assert(false, "SyntaxError not raised for :attribute_syntax => :normal")
126
+ end
127
+
128
+ begin
129
+ render("a\n :b c", :attribute_syntax => :alternate)
130
+ rescue Sass::SyntaxError => e
131
+ assert_equal("Illegal attribute syntax: can't use normal syntax when :attribute_syntax => :alternate is set.",
132
+ e.message)
133
+ else
134
+ assert(false, "SyntaxError not raised for :attribute_syntax => :alternate")
135
+ end
100
136
  end
137
+
138
+ def test_directive
139
+ assert_equal("@a b;", render("@a b"))
140
+
141
+ assert_equal("@a {\n b: c; }\n", render("@a\n :b c"))
142
+ assert_equal("@a { b: c; }\n", render("@a\n :b c", :style => :compact))
143
+ assert_equal("@a {\n b: c;\n}\n", render("@a\n :b c", :style => :expanded))
144
+ assert_equal("@a{b:c}\n", render("@a\n :b c", :style => :compressed))
145
+
146
+ assert_equal("@a {\n b: c;\n d: e; }\n",
147
+ render("@a\n :b c\n :d e"))
148
+ assert_equal("@a { b: c; d: e; }\n",
149
+ render("@a\n :b c\n :d e", :style => :compact))
150
+ assert_equal("@a {\n b: c;\n d: e;\n}\n",
151
+ render("@a\n :b c\n :d e", :style => :expanded))
152
+ assert_equal("@a{b:c;d:e}\n",
153
+ render("@a\n :b c\n :d e", :style => :compressed))
154
+
155
+ assert_equal("@a {\n #b {\n c: d; } }\n",
156
+ render("@a\n #b\n :c d"))
157
+ assert_equal("@a { #b { c: d; } }\n",
158
+ render("@a\n #b\n :c d", :style => :compact))
159
+ assert_equal("@a {\n #b {\n c: d;\n }\n}\n",
160
+ render("@a\n #b\n :c d", :style => :expanded))
161
+ assert_equal("@a{#b{c:d}}\n",
162
+ render("@a\n #b\n :c d", :style => :compressed))
163
+
164
+ assert_equal("@a {\n #b {\n a: b; }\n #b #c {\n d: e; } }\n",
165
+ render("@a\n #b\n :a b\n #c\n :d e"))
166
+ assert_equal("@a { #b { a: b; }\n #b #c { d: e; } }\n",
167
+ render("@a\n #b\n :a b\n #c\n :d e", :style => :compact))
168
+ assert_equal("@a {\n #b {\n a: b;\n }\n #b #c {\n d: e;\n }\n}\n",
169
+ render("@a\n #b\n :a b\n #c\n :d e", :style => :expanded))
170
+ assert_equal("@a{#b{a:b}#b #c{d:e}}\n",
171
+ render("@a\n #b\n :a b\n #c\n :d e", :style => :compressed))
172
+
173
+ assert_equal("@a {\n #foo,\n #bar {\n b: c; } }\n",
174
+ render("@a\n #foo, \n #bar\n :b c"))
175
+ assert_equal("@a { #foo, #bar { b: c; } }\n",
176
+ render("@a\n #foo, \n #bar\n :b c", :style => :compact))
177
+ assert_equal("@a {\n #foo,\n #bar {\n b: c;\n }\n}\n",
178
+ render("@a\n #foo, \n #bar\n :b c", :style => :expanded))
179
+ assert_equal("@a{#foo,#bar{b:c}}\n",
180
+ render("@a\n #foo, \n #bar\n :b c", :style => :compressed))
181
+
182
+ to_render = <<END
183
+ @a
184
+ :b c
185
+ #d
186
+ :e f
187
+ :g h
188
+ END
189
+ rendered = <<END
190
+ @a { b: c;
191
+ #d { e: f; }
192
+ g: h; }
193
+ END
194
+ assert_equal(rendered, render(to_render, :style => :compact))
101
195
 
196
+ assert_equal("@a{b:c;#d{e:f}g:h}\n", render(to_render, :style => :compressed))
197
+ end
198
+
199
+ def test_empty_first_line
200
+ assert_equal("#a {\n b: c; }\n", render("#a\n\n b: c"))
201
+ end
202
+
203
+ def test_escaped_rule
204
+ assert_equal(":focus {\n a: b; }\n", render("\\:focus\n a: b"))
205
+ assert_equal("a {\n b: c; }\n a :focus {\n d: e; }\n", render("\\a\n b: c\n \\:focus\n d: e"))
206
+ end
207
+
102
208
  private
103
209
 
210
+ def render(sass, options = {})
211
+ Sass::Engine.new(sass, options).render
212
+ end
213
+
104
214
  def renders_correctly(name, options={})
105
215
  sass_file = load_file(name, "sass")
106
216
  css_file = load_file(name, "css")
@@ -0,0 +1,18 @@
1
+ ***************
2
+ *** 44,49 ****
3
+ "@import templates/basic\n foo" => "Illegal nesting: Nothing may be nested beneath import directives.",
4
+ "foo\n @import templates/basic" => "Import directives may only be used at the root of a document.",
5
+ "@foo bar boom" => "Unknown compiler directive: \"@foo bar boom\"",
6
+ }
7
+
8
+ def test_basic_render
9
+ --- 44,52 ----
10
+ "@import templates/basic\n foo" => "Illegal nesting: Nothing may be nested beneath import directives.",
11
+ "foo\n @import templates/basic" => "Import directives may only be used at the root of a document.",
12
+ "@foo bar boom" => "Unknown compiler directive: \"@foo bar boom\"",
13
+ + "!foo = bar baz -" => "Unterminated unary minus.",
14
+ + "!foo = bar baz !" => "Unterminated constant.",
15
+ + "!foo = !(foo)" => "Invalid constant.",
16
+ }
17
+
18
+ def test_basic_render
@@ -22,7 +22,7 @@ class SassPluginTest < Test::Unit::TestCase
22
22
  set_plugin_opts
23
23
  Sass::Plugin.update_stylesheets
24
24
  end
25
-
25
+
26
26
  def teardown
27
27
  FileUtils.rm_r File.dirname(__FILE__) + '/tmp'
28
28
  end
@@ -30,14 +30,30 @@ class SassPluginTest < Test::Unit::TestCase
30
30
  def test_templates_should_render_correctly
31
31
  @@templates.each { |name| assert_renders_correctly(name) }
32
32
  end
33
-
33
+
34
34
  def test_no_update
35
35
  File.delete(tempfile_loc('basic'))
36
36
  assert Sass::Plugin.stylesheet_needs_update?('basic')
37
37
  Sass::Plugin.update_stylesheets
38
38
  assert !Sass::Plugin.stylesheet_needs_update?('basic')
39
39
  end
40
-
40
+
41
+ def test_update_needed_when_modified
42
+ sleep(1)
43
+ FileUtils.touch(template_loc('basic'))
44
+ assert Sass::Plugin.stylesheet_needs_update?('basic')
45
+ Sass::Plugin.update_stylesheets
46
+ assert !Sass::Plugin.stylesheet_needs_update?('basic')
47
+ end
48
+
49
+ def test_update_needed_when_dependency_modified
50
+ sleep(1)
51
+ FileUtils.touch(template_loc('basic'))
52
+ assert Sass::Plugin.stylesheet_needs_update?('import')
53
+ Sass::Plugin.update_stylesheets
54
+ assert !Sass::Plugin.stylesheet_needs_update?('import')
55
+ end
56
+
41
57
  def test_full_exception_handling
42
58
  File.delete(tempfile_loc('bork'))
43
59
  Sass::Plugin.update_stylesheets
@@ -57,13 +73,13 @@ class SassPluginTest < Test::Unit::TestCase
57
73
 
58
74
  Sass::Plugin.options[:full_exception] = true
59
75
  end
60
-
61
- def test_rails_update
76
+
77
+ def test_rails_update
62
78
  File.delete(tempfile_loc('basic'))
63
79
  assert Sass::Plugin.stylesheet_needs_update?('basic')
64
-
80
+
65
81
  ActionController::Base.new.process
66
-
82
+
67
83
  assert !Sass::Plugin.stylesheet_needs_update?('basic')
68
84
  end
69
85
 
@@ -87,20 +103,27 @@ class SassPluginTest < Test::Unit::TestCase
87
103
  assert !Sass::Plugin.stylesheet_needs_update?('basic')
88
104
  end
89
105
 
106
+ def test_doesnt_render_partials
107
+ assert !File.exists?(tempfile_loc('_partial'))
108
+ end
90
109
 
91
110
  private
92
-
111
+
93
112
  def assert_renders_correctly(name)
94
113
  File.read(result_loc(name)).split("\n").zip(File.read(tempfile_loc(name)).split("\n")).each_with_index do |pair, line|
95
114
  message = "template: #{name}\nline: #{line + 1}"
96
115
  assert_equal(pair.first, pair.last, message)
97
116
  end
98
117
  end
99
-
118
+
119
+ def template_loc(name)
120
+ File.dirname(__FILE__) + "/templates/#{name}.sass"
121
+ end
122
+
100
123
  def tempfile_loc(name)
101
124
  File.dirname(__FILE__) + "/tmp/#{name}.css"
102
125
  end
103
-
126
+
104
127
  def result_loc(name)
105
128
  File.dirname(__FILE__) + "/results/#{name}.css"
106
129
  end
@@ -124,7 +147,7 @@ end
124
147
 
125
148
  class Sass::Engine
126
149
  alias_method :old_render, :render
127
-
150
+
128
151
  def render
129
152
  raise "bork bork bork!" if @template[0] == "{bork now!}"
130
153
  old_render
@@ -1,5 +1,5 @@
1
1
  #main { width: 15em; color: #0000ff; }
2
- #main p { border-style: dotted; border-width: 2px; }
2
+ #main p { border-style: dotted; /* Nested comment More nested stuff */ border-width: 2px; }
3
3
  #main .cool { width: 100px; }
4
4
 
5
5
  #left { font-size: 2em; font-weight: bold; float: left; }
@@ -3,7 +3,7 @@ body { margin: 0; font: 0.85em "Lucida Grande", "Trebuchet MS", Verdana, sans-se
3
3
  #page { width: 900px; margin: 0 auto; background: #440008; border-top-width: 5px; border-top-style: solid; border-top-color: #ff8500; }
4
4
 
5
5
  #header { height: 75px; padding: 0; }
6
- #header h1 { float: left; width: 274px; height: 75px; margin: 0; background-image: url(/images/global_logo.gif); background-repeat: no-repeat; text-indent: -9999px; }
6
+ #header h1 { float: left; width: 274px; height: 75px; margin: 0; background-image: url(/images/global_logo.gif); /* Crazy nested comment */ background-repeat: no-repeat; text-indent: -9999px; }
7
7
  #header .status { float: right; padding-top: .5em; padding-left: .5em; padding-right: .5em; padding-bottom: 0; }
8
8
  #header .status p { float: left; margin-top: 0; margin-right: 0.5em; margin-bottom: 0; margin-left: 0; }
9
9
  #header .status ul { float: left; margin: 0; padding: 0; }