Class: Cassy

Inherits:
Object show all
Defined in:
lib/waves/views/cassy.rb

Overview

Markaby-ish way to declare CSS This code is based on code written by automatthew:

http://github.com/automatthew/cassandra/tree/master

Constant Summary collapse

HTML_TAGS =
%w( a abbr acronym address area b base bdo big blockquote body br button caption cite code col colgroup dd del dfn div dl dt em fieldset form 
h1 h2 h3 h4 h5 h6 head hr html i img input ins kbd label legend li link map meta noscript object ol optgroup option p param pre q samp script select 
small span strong style sub sup table tbody td textarea tfoot th thead title tr tt ul var )
CSS_PROPERTIES =
%w( azimuth background background_attachment background_color background_image background_position background_repeat border
border_left border_top border_right border_bottom border_collapse border_color border_spacing border_style border_top border_top_color border_top_style
border_top_width border_width bottom caption_side clear clip color content counter_increment counter_reset cue cue_after cue_before cursor
direction display elevation empty_cells float font font_family font_size font_size_adjust font_stretch font_style font_variant font_weight height
left letter_spacing line_height list_style list_style_image list_style_position list_style_type margin margin_left margin_top margin_right margin_bottom
marker_offset marks max_height max_width min_height min_width orphans outline outline_color outline_style outline_width overflow padding padding_left
padding_top padding_right padding_bottom page page_break_after page_break_before page_break_inside pause pause_after pause_before pitch pitch_range
play_during position quotes richness right size speak speak_header speak_numeral speak_punctuation speech_rate stress table_layout text_align
text_decoration text_indent text_shadow text_transform top unicode_bidi vertical_align visibility voice_family volume white_space widows width
word_spacing z_index )
METHODS =
%w( class include extend instance_eval send __send__ __id__ respond_to? )

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sel = nil) ⇒ Cassy

Returns a new instance of Cassy.



30
31
32
33
34
35
36
37
38
# File 'lib/waves/views/cassy.rb', line 30

def initialize(sel=nil)
  @data = []
  @selectors = [ sel ]
  @properties = []
  
  # Primitive state machine
  # possible states are :closed_block, :chain, :open_block
  @state = :closed_block
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, &block) ⇒ Object

Catch unknown methods and treat them as CSS class or id selectors.



83
84
85
86
87
88
89
90
91
92
93
# File 'lib/waves/views/cassy.rb', line 83

def method_missing(name, &block)
  sel = selectify(name)
  if block_given?
    open_block(sel)
    yield
    closed_block
  else
    chain(sel)
  end
  self
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



28
29
30
# File 'lib/waves/views/cassy.rb', line 28

def data
  @data
end

Class Method Details

.process(*args, &block) ⇒ Object



40
41
42
# File 'lib/waves/views/cassy.rb', line 40

def self.process(*args,&block)
  self.new.process(*args,&block)
end

Instance Method Details

#chain(new_selector) ⇒ Object

Pushes accumulated selector on the stack without generating a new properties array.



145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/waves/views/cassy.rb', line 145

def chain(new_selector)
  case @state
  when :closed_block, :open_block
    combined_selector = [@selectors[-1], new_selector].compact.join(" ")
    @selectors.push( combined_selector)
  when :chain
    @selectors[-1] = "#{@selectors[-1]}#{new_selector}"
  else
    raise "You can't get to :chain from #{@state.inspect}"
  end
  
  @state = :chain
end

#closed_blockObject

Pop the selector string and property array for the closing block off of their respective stacks



161
162
163
164
165
166
167
168
169
170
171
# File 'lib/waves/views/cassy.rb', line 161

def closed_block
  case @state
  when :open_block, :closed_block
    @selectors.pop
    @properties.pop
  else
    raise "You can't get to :closed_block from #{@state.inspect}"
  end
  
  @state = :closed_block
end

#new_property_setObject

Pushes an empty array on the properties stack and registers that array (against the current selector) in @data



64
65
66
67
# File 'lib/waves/views/cassy.rb', line 64

def new_property_set
  @properties.push []
  @data << [@selectors[-1], @properties[-1] ]
end

#open_block(new_selector) ⇒ Object

Push the accumulated selector and a new property array onto the tops of their respected stacks



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/waves/views/cassy.rb', line 128

def open_block(new_selector)
  case @state
  when :closed_block, :open_block
    combined_selector = [@selectors[-1], new_selector].compact.join(" ")
    @selectors.push combined_selector
    new_property_set
  when :chain
    @selectors[-1] = "#{@selectors[-1]}#{new_selector}"
    new_property_set
  else
    raise "You can't get to :open_block from #{@state.inspect}"
  end
  
  @state = :open_block
end

#process(*args, &block) ⇒ Object



44
45
46
47
48
49
50
51
# File 'lib/waves/views/cassy.rb', line 44

def process(*args, &block)
  if block
    instance_eval(&block)
  else
    instance_eval(args.join("\n"))
  end
  self
end

#property(css_attr, *args) ⇒ Object

Add a property declaration string to the current selector’s properties array.



120
121
122
# File 'lib/waves/views/cassy.rb', line 120

def property(css_attr, *args)
  @properties[-1] << "#{css_attr}: #{args.join(' ')};"
end

#selectify(method_name) ⇒ Object

bang methods represent CSS ids. Otherwise CSS classes.



96
97
98
99
# File 'lib/waves/views/cassy.rb', line 96

def selectify(method_name)
  matches = method_name.to_s.match( /([\w_]+)!$/)
  matches ? "##{matches[1]}" : ".#{method_name}"
end

#selector(sel) ⇒ Object

Declare a CSS selector using a block. May be chained and nested.



71
72
73
74
75
76
77
78
79
80
# File 'lib/waves/views/cassy.rb', line 71

def selector(sel)
  if block_given?
    open_block(sel)
    yield
    closed_block
  else
    chain(sel)
  end
  self
end

#to_sObject



53
54
55
56
57
58
# File 'lib/waves/views/cassy.rb', line 53

def to_s
  @data.map do |sel|
    properties = sel.last.join("\n  ")
    "#{sel.first} {\n  #{properties}\n}\n"
  end.join
end