~michaelforrest/use-case-mapper/trunk

« back to all changes in this revision

Viewing changes to vendor/rails/activesupport/lib/active_support/vendor/builder-2.1.2/builder/css.rb

  • Committer: Richard Lee (Canonical)
  • Date: 2010-10-15 15:17:58 UTC
  • mfrom: (190.1.3 use-case-mapper)
  • Revision ID: richard.lee@canonical.com-20101015151758-wcvmfxrexsongf9d
Merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
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