3 # Copyright 2004, 2005 by Jim Weirich (jim@weirichhouse.org).
4 # Copyright 2005 by Scott Barron (scott@elitists.net).
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.
17 # Provide a flexible and easy to use Builder for creating Cascading
21 require 'builder/blankslate'
25 # Create a Cascading Style Sheet (CSS) using Ruby.
29 # css = Builder::CSS.new
31 # text_color = '#7F7F7F'
32 # preferred_fonts = 'Helvetica, Arial, sans_serif'
34 # css.comment! 'This is our stylesheet'
36 # background_color '#FAFAFA'
38 # font_family preferred_fonts
46 # css.class!('navitem') {
51 # text_decoration 'underline'
54 # css.div(:id => 'menu') {
58 # css.div(:class => 'foo') {
62 # This will yield the following stylesheet:
64 # /* This is our stylesheet */
66 # background_color: #FAFAFA;
68 # font_family: Helvetica, Arial, sans_serif;
81 # text_decoration: underline;
92 class CSS
< BlankSlate
94 # Create a CSS builder.
96 # out:: Object receiving the markup.1 +out+ must respond to
98 # indent:: Number of spaces used for indentation (0 implies no
99 # indentation and no line breaks).
101 def initialize(indent
=2)
128 # Return the target of the builder
133 # Create a comment string in the output.
134 def comment
!(comment_text
)
135 @target << "/* #{comment_text} */\n"
139 _start_container('#'+arg
.to_s
, nil, block_given
?)
140 _css_block(block
) if block
145 def class!(arg
, &block
)
146 _start_container('.'+arg
.to_s
, nil, block_given
?)
147 _css_block(block
) if block
152 def store
!(sym
, &block
)
153 @library[sym
] = block
.to_proc
156 def group
!(*args
, &block
)
159 instance_eval(&@library[arg
])
163 _text
', ' unless arg
== args
.last
171 def method_missing(sym
, *args
, &block
)
172 sym
= "#{sym}:#{args.shift}" if args
.first
.kind_of
?(Symbol
)
174 _start_container(sym
, args
.first
)
179 _css_line(sym
, *args
)
183 _start_container(sym
, args
.first
, false)
189 # "Cargo culted" from Jim who also "cargo culted" it. See xmlbase.rb.
196 @target << @parts * ''
200 def _join_with_op
!(op
)
201 rhs
, lhs
= @target.pop
, @target.pop
202 @target << "#{lhs} #{op} #{rhs}"
209 def _css_block(block
)
211 _nested_structures(block
)
229 def _nested_structures(block
)
231 self.instance_eval(&block
)
235 def _start_container(sym
, atts
= {}, with_bracket
= true)
237 selector
<< ".#{atts[:class]}" if atts
&& atts
[:class]
238 selector
<< '#' + "#{atts[:id]}" if atts
&& atts
[:id]
239 @parts << "#{selector}#{with_bracket ? ' {' : ''}"
246 def _css_line(sym
, *args
)
247 _text("#{sym.to_s.gsub('_','-')}: #{args * ' '};")