756e6d2ad8
* This will significantly decrease the size of the msf install (~5 MB) * ActiveRecord & ActiveSupport are still used, and have been moved to lib/ git-svn-id: file:///home/svn/framework3/trunk@10682 4d416f70-5f16-0410-b530-b9f4589650da
251 lines
5.2 KiB
Ruby
251 lines
5.2 KiB
Ruby
#!/usr/bin/env ruby
|
|
#--
|
|
# Copyright 2004, 2005 by Jim Weirich (jim@weirichhouse.org).
|
|
# Copyright 2005 by Scott Barron (scott@elitists.net).
|
|
# All rights reserved.
|
|
#
|
|
# Permission is granted for use, copying, modification, distribution,
|
|
# and distribution of modified versions of this work as long as the
|
|
# above copyright notice is included.
|
|
#
|
|
# Much of this is taken from Jim's work in xmlbase.rb and xmlmarkup.rb.
|
|
# Documentation has also been copied and pasted and modified to reflect
|
|
# that we're building CSS here instead of XML. Jim is conducting the
|
|
# orchestra here and I'm just off in the corner playing a flute.
|
|
#++
|
|
|
|
# Provide a flexible and easy to use Builder for creating Cascading
|
|
# Style Sheets (CSS).
|
|
|
|
|
|
require 'builder/blankslate'
|
|
|
|
module Builder
|
|
|
|
# Create a Cascading Style Sheet (CSS) using Ruby.
|
|
#
|
|
# Example usage:
|
|
#
|
|
# css = Builder::CSS.new
|
|
#
|
|
# text_color = '#7F7F7F'
|
|
# preferred_fonts = 'Helvetica, Arial, sans_serif'
|
|
#
|
|
# css.comment! 'This is our stylesheet'
|
|
# css.body {
|
|
# background_color '#FAFAFA'
|
|
# font_size 'small'
|
|
# font_family preferred_fonts
|
|
# color text_color
|
|
# }
|
|
#
|
|
# css.id!('navbar') {
|
|
# width '500px'
|
|
# }
|
|
#
|
|
# css.class!('navitem') {
|
|
# color 'red'
|
|
# }
|
|
#
|
|
# css.a :hover {
|
|
# text_decoration 'underline'
|
|
# }
|
|
#
|
|
# css.div(:id => 'menu') {
|
|
# background 'green'
|
|
# }
|
|
#
|
|
# css.div(:class => 'foo') {
|
|
# background 'red'
|
|
# }
|
|
#
|
|
# This will yield the following stylesheet:
|
|
#
|
|
# /* This is our stylesheet */
|
|
# body {
|
|
# background_color: #FAFAFA;
|
|
# font_size: small;
|
|
# font_family: Helvetica, Arial, sans_serif;
|
|
# color: #7F7F7F;
|
|
# }
|
|
#
|
|
# #navbar {
|
|
# width: 500px;
|
|
# }
|
|
#
|
|
# .navitem {
|
|
# color: red;
|
|
# }
|
|
#
|
|
# a:hover {
|
|
# text_decoration: underline;
|
|
# }
|
|
#
|
|
# div#menu {
|
|
# background: green;
|
|
# }
|
|
#
|
|
# div.foo {
|
|
# background: red;
|
|
# }
|
|
#
|
|
class CSS < BlankSlate
|
|
|
|
# Create a CSS builder.
|
|
#
|
|
# out:: Object receiving the markup.1 +out+ must respond to
|
|
# <tt><<</tt>.
|
|
# indent:: Number of spaces used for indentation (0 implies no
|
|
# indentation and no line breaks).
|
|
#
|
|
def initialize(indent=2)
|
|
@indent = indent
|
|
@target = []
|
|
@parts = []
|
|
@library = {}
|
|
end
|
|
|
|
def +(part)
|
|
_join_with_op! '+'
|
|
self
|
|
end
|
|
|
|
def >>(part)
|
|
_join_with_op! ''
|
|
self
|
|
end
|
|
|
|
def >(part)
|
|
_join_with_op! '>'
|
|
self
|
|
end
|
|
|
|
def |(part)
|
|
_join_with_op! ','
|
|
self
|
|
end
|
|
|
|
# Return the target of the builder
|
|
def target!
|
|
@target * ''
|
|
end
|
|
|
|
# Create a comment string in the output.
|
|
def comment!(comment_text)
|
|
@target << "/* #{comment_text} */\n"
|
|
end
|
|
|
|
def id!(arg, &block)
|
|
_start_container('#'+arg.to_s, nil, block_given?)
|
|
_css_block(block) if block
|
|
_unify_block
|
|
self
|
|
end
|
|
|
|
def class!(arg, &block)
|
|
_start_container('.'+arg.to_s, nil, block_given?)
|
|
_css_block(block) if block
|
|
_unify_block
|
|
self
|
|
end
|
|
|
|
def store!(sym, &block)
|
|
@library[sym] = block.to_proc
|
|
end
|
|
|
|
def group!(*args, &block)
|
|
args.each do |arg|
|
|
if arg.is_a?(Symbol)
|
|
instance_eval(&@library[arg])
|
|
else
|
|
instance_eval(&arg)
|
|
end
|
|
_text ', ' unless arg == args.last
|
|
end
|
|
if block
|
|
_css_block(block)
|
|
_unify_block
|
|
end
|
|
end
|
|
|
|
def method_missing(sym, *args, &block)
|
|
sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
|
|
if block
|
|
_start_container(sym, args.first)
|
|
_css_block(block)
|
|
_unify_block
|
|
elsif @in_block
|
|
_indent
|
|
_css_line(sym, *args)
|
|
_newline
|
|
return self
|
|
else
|
|
_start_container(sym, args.first, false)
|
|
_unify_block
|
|
end
|
|
self
|
|
end
|
|
|
|
# "Cargo culted" from Jim who also "cargo culted" it. See xmlbase.rb.
|
|
def nil?
|
|
false
|
|
end
|
|
|
|
private
|
|
def _unify_block
|
|
@target << @parts * ''
|
|
@parts = []
|
|
end
|
|
|
|
def _join_with_op!(op)
|
|
rhs, lhs = @target.pop, @target.pop
|
|
@target << "#{lhs} #{op} #{rhs}"
|
|
end
|
|
|
|
def _text(text)
|
|
@parts << text
|
|
end
|
|
|
|
def _css_block(block)
|
|
_newline
|
|
_nested_structures(block)
|
|
_end_container
|
|
_end_block
|
|
end
|
|
|
|
def _end_block
|
|
_newline
|
|
_newline
|
|
end
|
|
|
|
def _newline
|
|
_text "\n"
|
|
end
|
|
|
|
def _indent
|
|
_text ' ' * @indent
|
|
end
|
|
|
|
def _nested_structures(block)
|
|
@in_block = true
|
|
self.instance_eval(&block)
|
|
@in_block = false
|
|
end
|
|
|
|
def _start_container(sym, atts = {}, with_bracket = true)
|
|
selector = sym.to_s
|
|
selector << ".#{atts[:class]}" if atts && atts[:class]
|
|
selector << '#' + "#{atts[:id]}" if atts && atts[:id]
|
|
@parts << "#{selector}#{with_bracket ? ' {' : ''}"
|
|
end
|
|
|
|
def _end_container
|
|
@parts << "}"
|
|
end
|
|
|
|
def _css_line(sym, *args)
|
|
_text("#{sym.to_s.gsub('_','-')}: #{args * ' '};")
|
|
end
|
|
end
|
|
end
|