Froze rails gems
[depot.git] / vendor / rails / activesupport / lib / active_support / vendor / builder-2.1.2 / builder / css.rb
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.
6 #
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.
10 #
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 #++
16
17 # Provide a flexible and easy to use Builder for creating Cascading
18 # Style Sheets (CSS).
19
20
21 require 'builder/blankslate'
22
23 module Builder
24
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
93
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
107
108 def +(part)
109 _join_with_op! '+'
110 self
111 end
112
113 def >>(part)
114 _join_with_op! ''
115 self
116 end
117
118 def >(part)
119 _join_with_op! '>'
120 self
121 end
122
123 def |(part)
124 _join_with_op! ','
125 self
126 end
127
128 # Return the target of the builder
129 def target!
130 @target * ''
131 end
132
133 # Create a comment string in the output.
134 def comment!(comment_text)
135 @target << "/* #{comment_text} */\n"
136 end
137
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
144
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
151
152 def store!(sym, &block)
153 @library[sym] = block.to_proc
154 end
155
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
170
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
188
189 # "Cargo culted" from Jim who also "cargo culted" it. See xmlbase.rb.
190 def nil?
191 false
192 end
193
194 private
195 def _unify_block
196 @target << @parts * ''
197 @parts = []
198 end
199
200 def _join_with_op!(op)
201 rhs, lhs = @target.pop, @target.pop
202 @target << "#{lhs} #{op} #{rhs}"
203 end
204
205 def _text(text)
206 @parts << text
207 end
208
209 def _css_block(block)
210 _newline
211 _nested_structures(block)
212 _end_container
213 _end_block
214 end
215
216 def _end_block
217 _newline
218 _newline
219 end
220
221 def _newline
222 _text "\n"
223 end
224
225 def _indent
226 _text ' ' * @indent
227 end
228
229 def _nested_structures(block)
230 @in_block = true
231 self.instance_eval(&block)
232 @in_block = false
233 end
234
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
241
242 def _end_container
243 @parts << "}"
244 end
245
246 def _css_line(sym, *args)
247 _text("#{sym.to_s.gsub('_','-')}: #{args * ' '};")
248 end
249 end
250 end