Class: CascadingRubies

Inherits:
BlankSlate show all
Defined in:
lib/cascading_rubies.rb

Overview

:doc:

Constant Summary collapse

TAGS =

List of tags taken from www.w3schools.com/tags/default.asp

%w(a abbr acronym address applet area b base basefont bdo big blockquote body br button caption center cite code col colgroup dd del dir div dfn dl dt em fieldset font form frame frameset h1 h2 h3 h4 h5 h6 head hr html i iframe img input ins isindex kbd label legend li link map meta noframes noscript object ol optgroup option p param pre q samp script select small span strike strong style sub sup table tbody td textarea tfoot th thead title tr tt u ul var xmp)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BlankSlate

find_hidden_method, hide, reveal

Constructor Details

#initialize(context_name = nil, selectors = [], classed = false, &dsl_code) ⇒ CascadingRubies

Creates a CascadingRubies object. Normally, you should not pass in any arguments, except a block of style definitions. The block can optionally take a single argument – if so, the newly created object is yielded to the block, and instance_eval is not used.

Each block in the style definitions is effectively going to trigger a new object to be created, so the block argument is optional for each block, and the determination to use instance_eval is subsequently per block:

CascadingRubies.new do |css|
  css.header do |header|
    header.background_color '#ccc'
  end
  css.p {
    margin_bottom '15px'
  }
end

If you do not pass a block (or even if you do), you can execute additional style definitions by either calling methods directly on the object:

obj = CascadingRubies.new
obj.nav { margin '10px'; a { color :red } }

or you can instance_eval another block of code:

obj.instance_eval do
  p { margin_bottom '15px' }
end


40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/cascading_rubies.rb', line 40

def initialize(context_name=nil, selectors=[], classed=false, &dsl_code)
  @__context_name = context_name
  @__css = ''
  @__selectors = selectors
  @__classed = classed # if true, method_missing calls are css class selectors -- not id selectors
  if dsl_code.nil?
    # do nothing
  elsif dsl_code.arity == 1
    dsl_code[self]
  else
    instance_eval(&dsl_code)
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &dsl_code) ⇒ Object

:nodoc:



83
84
85
86
87
# File 'lib/cascading_rubies.rb', line 83

def method_missing(method_name, *args, &dsl_code) #:nodoc:
  @__has_children = true
  selector = dsl_code ? __method_name_to_selector(method_name) : __dashify(method_name)
  s(selector, *args, &dsl_code)
end

Instance Attribute Details

#__context_nameObject (readonly)

:nodoc:



14
15
16
# File 'lib/cascading_rubies.rb', line 14

def __context_name
  @__context_name
end

#__cssObject (readonly)

:nodoc:



14
15
16
# File 'lib/cascading_rubies.rb', line 14

def __css
  @__css
end

#__has_childrenObject (readonly)

:nodoc:



14
15
16
# File 'lib/cascading_rubies.rb', line 14

def __has_children
  @__has_children
end

#__selectorsObject (readonly)

:nodoc:



14
15
16
# File 'lib/cascading_rubies.rb', line 14

def __selectors
  @__selectors
end

Class Method Details

.css(code = nil, &block) ⇒ Object

Wraps the creation of a CascadingRubies object and doing the instance_eval execution in a neat package for use inside rcss files. An rcss file can use the optional block syntax to wrap style definitions, allowing code to be run outside the instance_eval confines. Use this method in an .rcss file like so:

css do
  a { color :red }
end

or:

CascadingRubies.css do
  a { color :red }
end


116
117
118
119
120
121
122
123
# File 'lib/cascading_rubies.rb', line 116

def self.css(code=nil, &block)
  @obj = self.new
  if code
    @obj.instance_eval(code)
  else
    @obj.instance_eval(&block)
  end
end

.open(path) ⇒ Object

Creates a CascadingRubies object, then opens the file and executes the style definitions in the context of the object. Returns the newly created object.



96
97
98
99
100
101
102
103
# File 'lib/cascading_rubies.rb', line 96

def self.open(path)
  if (code = File.read(path)) =~ /^css do|CascadingRubies\.css do/
    eval(code)
  else
    css(code)
  end
  @obj
end

Instance Method Details

#s(selector, *args, &dsl_code) ⇒ Object

Create a new style “selector” without going through method_missing. Use this to create style definitions that cannot be created with the DSL directly, e.g.

  • s('##s') { color :blue } => ##s { color: blue; }

  • s('div##search') { margin 0 } => div##search { margin: 0; }



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/cascading_rubies.rb', line 58

def s(selector, *args, &dsl_code)
  if args.any? and dsl_code.nil? # css rule
    @__css << "#{selector}: #{args.join(' ')}; "
  else
    if args.any? and dsl_code # pseudo-class selector
      selector_name = args.map do |arg|
        [[@__context_name, selector].compact.join(' '), ':' + arg.to_s].join('')
      end.join(', ')
    else # regular selector
      selector_name = [@__context_name, selector].compact.join(@__classed ? '' : ' ')
    end
    if @__bare and not @__bare.__has_children # e.g. li; a { }
      selector_name = "#{@__bare.__context_name}, #{selector_name}"
    end
    if dsl_code
      compiled = self.class.new(selector_name, &dsl_code)
      @__selectors << "#{selector_name} { #{compiled.__css}}" unless compiled.__css.empty?
      @__selectors += compiled.__selectors
      @__bare = nil
    else # e.g. div.something
      @__bare = self.class.new(selector_name, @__selectors, true, &dsl_code)
    end
  end
end

#to_sObject

Returns the complete CSS style definitions as a string.



90
91
92
# File 'lib/cascading_rubies.rb', line 90

def to_s
  @__selectors.join("\n")
end