Upgraded Rails and RSpec
[monkeycharger.git] / vendor / rails / activesupport / lib / active_support / vendor / builder-2.1.2 / builder / css.rb
blobe086a1b132dc33c8851c8fc2c4065bc7b64a20a2
1 #!/usr/bin/env ruby
2 #--
3 # Copyright 2004, 2005 by Jim Weirich  (jim@weirichhouse.org).
4 # Copyright       2005 by Scott Barron (scott@elitists.net).
5 # All rights reserved.
7 # Permission is granted for use, copying, modification, distribution,
8 # and distribution of modified versions of this work as long as the
9 # above copyright notice is included.
11 # Much of this is taken from Jim's work in xmlbase.rb and xmlmarkup.rb.
12 # Documentation has also been copied and pasted and modified to reflect
13 # that we're building CSS here instead of XML.  Jim is conducting the
14 # orchestra here and I'm just off in the corner playing a flute.
15 #++
17 # Provide a flexible and easy to use Builder for creating Cascading
18 # Style Sheets (CSS).
21 require 'builder/blankslate'
23 module Builder
25   # Create a Cascading Style Sheet (CSS) using Ruby.
26   #
27   # Example usage:
28   #
29   #   css = Builder::CSS.new
30   #
31   #   text_color      = '#7F7F7F'
32   #   preferred_fonts = 'Helvetica, Arial, sans_serif'
33   #
34   #   css.comment! 'This is our stylesheet'
35   #   css.body {
36   #     background_color '#FAFAFA'
37   #     font_size        'small'
38   #     font_family      preferred_fonts
39   #     color            text_color
40   #   }
41   #
42   #   css.id!('navbar') {
43   #     width            '500px'
44   #   }
45   #
46   #   css.class!('navitem') {
47   #     color            'red'
48   #   }
49   #
50   #   css.a :hover {
51   #     text_decoration  'underline'
52   #   }
53   #
54   #   css.div(:id => 'menu') {
55   #     background       'green'
56   #   }
57   #
58   #   css.div(:class => 'foo') {
59   #     background       'red'
60   #   }
61   #
62   # This will yield the following stylesheet:
63   #
64   #   /* This is our stylesheet */
65   #   body {
66   #     background_color: #FAFAFA;
67   #     font_size:        small;
68   #     font_family:      Helvetica, Arial, sans_serif;
69   #     color:            #7F7F7F;
70   #   }
71   #
72   #   #navbar {
73   #     width:            500px;
74   #   }
75   #
76   #   .navitem {
77   #     color:            red;
78   #   }
79   #
80   #   a:hover {
81   #     text_decoration:  underline;
82   #   }
83   #
84   #   div#menu {
85   #     background:       green;
86   #   }
87   #
88   #   div.foo {
89   #     background:       red;
90   #   }
91   #
92   class CSS < BlankSlate
94     # Create a CSS builder.
95     #
96     # out::     Object receiving the markup.1  +out+ must respond to
97     #           <tt><<</tt>.
98     # indent::  Number of spaces used for indentation (0 implies no
99     #           indentation and no line breaks).
100     #
101     def initialize(indent=2)
102       @indent      = indent
103       @target      = []
104       @parts       = []
105       @library     = {}
106     end
108     def +(part)
109       _join_with_op! '+'
110       self
111     end
113     def >>(part)
114       _join_with_op! ''
115       self
116     end
118     def >(part)
119       _join_with_op! '>'
120       self
121     end
123     def |(part)
124       _join_with_op! ','
125       self
126     end
128     # Return the target of the builder
129     def target!
130       @target * ''
131     end
133     # Create a comment string in the output.
134     def comment!(comment_text)
135       @target << "/* #{comment_text} */\n"
136     end
138     def id!(arg, &block)
139       _start_container('#'+arg.to_s, nil, block_given?)
140       _css_block(block) if block
141       _unify_block
142       self
143     end
145     def class!(arg, &block)
146       _start_container('.'+arg.to_s, nil, block_given?)
147       _css_block(block) if block
148       _unify_block
149       self
150     end
152     def store!(sym, &block)
153       @library[sym] = block.to_proc
154     end
156     def group!(*args, &block)
157       args.each do |arg|
158         if arg.is_a?(Symbol)
159           instance_eval(&@library[arg])
160         else
161           instance_eval(&arg)
162         end
163         _text ', ' unless arg == args.last
164       end
165       if block
166         _css_block(block)
167         _unify_block
168       end
169     end
171     def method_missing(sym, *args, &block)
172       sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
173       if block
174         _start_container(sym, args.first)
175         _css_block(block)
176         _unify_block
177       elsif @in_block
178         _indent
179         _css_line(sym, *args)
180         _newline
181         return self
182       else
183         _start_container(sym, args.first, false)
184         _unify_block
185       end
186       self
187     end
189     # "Cargo culted" from Jim who also "cargo culted" it.  See xmlbase.rb.
190     def nil?
191       false
192     end
194     private
195     def _unify_block
196       @target << @parts * ''
197       @parts = []
198     end
200     def _join_with_op!(op)
201       rhs, lhs = @target.pop, @target.pop
202       @target << "#{lhs} #{op} #{rhs}"
203     end
205     def _text(text)
206       @parts << text
207     end
209     def _css_block(block)
210       _newline
211       _nested_structures(block)
212       _end_container
213       _end_block
214     end
216     def _end_block
217       _newline
218       _newline
219     end
221     def _newline
222       _text "\n"
223     end
225     def _indent
226       _text ' ' * @indent
227     end
229     def _nested_structures(block)
230       @in_block = true
231       self.instance_eval(&block)
232       @in_block = false
233     end
235     def _start_container(sym, atts = {}, with_bracket = true)
236       selector = sym.to_s
237       selector << ".#{atts[:class]}" if atts && atts[:class]
238       selector << '#' + "#{atts[:id]}" if atts && atts[:id]
239       @parts << "#{selector}#{with_bracket ? ' {' : ''}"
240     end
242     def _end_container
243       @parts << "}"
244     end
246     def _css_line(sym, *args)
247       _text("#{sym.to_s.gsub('_','-')}: #{args * ' '};")
248     end
249   end