File: active_support/vendor/builder-2.1.2/builder/css.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: Builder#23
  class: CSS#92
inherits from
  BlankSlate   
has properties
method: initialize / 1 #101
method: + / 1 #108
method: >> / 1 #113
method: > / 1 #118
method: | / 1 #123
method: target! #129
method: comment! / 1 #134
method: id! / 2 #138
method: class! / 2 #145
method: store! / 2 #152
method: group! / 2 #156
method: method_missing / 3 #171
method: nil? #190
method: _unify_block #195
method: _join_with_op! / 1 #200
method: _text / 1 #205
method: _css_block / 1 #209
method: _end_block #216
method: _newline #221
method: _indent #225
method: _nested_structures / 1 #229
method: _start_container / 3 #235
method: _end_container #242
method: _css_line / 2 #246

Class Hierarchy

Object ( Builtin-Module )
BlankSlate
  CSS ( Builder ) #92

Code

   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