Class: Jig::CSS

Inherits:
Jig
  • Object
show all
Defined in:
lib/jig/css.rb

Overview

Jig::CSS is a subclass of Jig designed to facilitate the construction of CSS rule sets. This class should be considered experimental. The documentation uses C instead Jig::CSS to simplify the examples.

An instance of Jig::CSS represents a CSS rule consisting of a selector list and an associated declaration block. The selector list or the delcaration block or both may be empty. Declarations are specified via a hash.

C.new                         # => {}
C.new('h1')                   # => h1 {}
C.new(nil, 'color' => 'red')  # => {color: red; }

A simple CSS type selector with an empty declaration is the default construction:

C.div                         # => div {}
C.li                          # => li {}

Rules can be combined with each other or with a hash via the ‘pipe’ operator.

big = { 'font-size' => '24pt' }
bold = { 'font-weight' => 'bold' }
big_div = C.div | big                 # => div {font-size: 24pt; }
big_bold_div = bigger | bold          # => div {font-size: 24pt; font-weight: bold; }
C.h1 | C.h2                           # => h1, h2 { }
C.h1 | big | C.h2 | bold              # => h1, h2 { font-size: 24pt; font-weight: bold; }

Defined Under Namespace

Modules: FloatHelper, IntegerHelper

Constant Summary collapse

Newlines =
[:html, :head, :body, :title, :div, :p, :table, :script, :form]
Encode =

Constants inherited from Jig

Before, DEFAULT_GAP, GAP, Replace, VERSION

Instance Attribute Summary

Attributes inherited from Jig

#contents, #rawgaps

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Jig

#==, #===, #=~, #after, #after!, #before, #before!, #closed?, #concat, #eql?, #fill!, #filln!, #freeze, #gaps, #has_gap?, #index, #initialize_copy, #inspect, interpolate, #join, #mult, null, #null?, #open?, parse, parse_other, #plug, #plug!, #plug_gap!, #plugn, #plugn!, #push, #push_jig, #slice, #split, #syntax, #to_s

Constructor Details

#initialize(selector = '*', declarations = nil) ⇒ CSS

Construct a CSS rule.



76
77
78
# File 'lib/jig/css.rb', line 76

def initialize(selector='*', declarations=nil)
  super(selector, :__s, " {", :__ds, to_declarations(declarations),  :__de, "}").freeze
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, declarations = nil) ⇒ Object

Missing methods are rewritten as calls to #class_, which constructs class selectors.

C.div.class_('urgent')        # => div.urgent {}
C.div.urgent                  # => div.urgent {}
C.div.note.caution            # => div.note.caution {}


256
257
258
# File 'lib/jig/css.rb', line 256

def method_missing(sym, declarations=nil)
  class_(sym, declarations)
end

Class Method Details

.import(url, *types) ⇒ Object



70
71
72
# File 'lib/jig/css.rb', line 70

def import(url, *types)
  Jig.new("@import url(\"#{url}\") #{types.join(', ')}")
end

.media(*types) ⇒ Object



65
66
67
68
# File 'lib/jig/css.rb', line 65

def media(*types)
  indent = Gap.new(:___) { |text| Jig.new { text.to_s.split("\n").map { |line| "  #{line}" }.join("\n")}  }
  Jig.new("@media #{types.join(', ')} {\n", indent, "\n}\n")
end

.method_missing(sym, *args) ⇒ Object

Construct a simple type selector based on the method name.

C.new('div')    # => div {}
C.div           # => div {}


61
62
63
# File 'lib/jig/css.rb', line 61

def method_missing(sym, *args)
  new(sym.to_s, *args)
end

Instance Method Details

#*(id) ⇒ Object

Construct an id selector. The id is the rhs value.

h1 * 'chapter-one'     # => "h1#chapter-one {}"


156
157
158
# File 'lib/jig/css.rb', line 156

def *(id)
  before(:__s, "#", id.to_s)
end

#+(other) ⇒ Object

Construct an adjacent sibling selector. The first sibling is the lhs selector and the other sibling is rhs selector.

h1 + p     # => "h1 + p {}"


143
144
145
# File 'lib/jig/css.rb', line 143

def +(other)
  before(:__s, " + ", other.selector).before(:__de, other.declarations)
end

#-(other) ⇒ Object

Construct a negation pseudo class. The delcarations associated with the other selector are discarded.

div - p     # => "div:not(p) {}"


177
178
179
# File 'lib/jig/css.rb', line 177

def -(other)
  before(:__s, ":not(", other.selector, ")")
end

#/(pseudo) ⇒ Object

Construct a pseudo-selector.

h1/:first_letter      # => "h1:first-letter {}"
a/:active             # => "a:active {}"


163
164
165
# File 'lib/jig/css.rb', line 163

def /(pseudo)
  before(:__s, ":", pseudo.to_s)
end

#>(other) ⇒ Object

Construct a child selector. The parent is the lhs selector and the child is the rhs selector.

div > p     # => "div > p {}"


136
137
138
# File 'lib/jig/css.rb', line 136

def >(other)
  before(:__s, " > ", other.selector).before(:__de, other.declarations)
end

#>>(other) ⇒ Object

Construct a descendent selector. The parent is the lhs selector and the descendent is the rhs selector.

div >> p     # => "div p {}"


170
171
172
# File 'lib/jig/css.rb', line 170

def >>(other)
  before(:__s, " ", other.selector).before(:__de, other.declarations)
end

#[](*args) ⇒ Object

Construct an attribute selector. If the argument is a simple string a simple attribute selector is constructed. If the argument is a hash with a string as the value, an exact attribute selector is constructed. If the value is a regular expression, a partial attribute selector is constructed. If the key is the literal string ‘lang’, a language attribute selector is constructed.

input[:type]                # => input[type] {}
input[:type => 'password']  # => input[type="password"] {}
input[:lang => 'en']        # => input[lang|="en"] {}
input[:class => /heading/]  # => input[class=~"heading"] {}


280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/jig/css.rb', line 280

def [](*args)
  if args.size == 1 && args.first.respond_to?(:to_hash) && args.first.size == 1
    k,v = *args.first.to_a.first
    case v
    when String
      before(:__s, %Q{[#{k}="#{v}"]})
    when Regexp
      v = v.to_s.split(':').last.chop    # strip out the processing flags
      if k.to_s == 'lang'
        before(:__s, %Q{[lang|="#{v}"]})
      else
        before(:__s, %Q{[#{k}~="#{v}"]})
      end
    else
      self
    end
  elsif args.size == 1 && args.first.respond_to?(:to_s)
    before(:__s, "[#{args.first}]")
  else
    self
  end
end

#class_(klass, declarations = nil) ⇒ Object

Add a class selector to pending selector. Usually this method is called indirectly via method_missing.

C.div.class_('urgent')        # => div.urgent {}
C.div.urgent                  # => div.urgent {}


264
265
266
# File 'lib/jig/css.rb', line 264

def class_(klass, declarations=nil)
  before(:__s, ".#{klass}") | declarations
end

#declaration(property, value) ⇒ Object

Convert property/value pair for use in a CSS rule jig. Any underscores in the property are converted to hyphens. If the property ends in ‘!’, the ‘!’ is stripped and the declaration is marked with the CSS keyword ‘!important’.

  • If value is nil or false, the empty string is returned.

  • If value is a symbol, a declaration gap is returned.

  • If value is a gap, the gap is returned.

  • If value is a proc, method, or jig, a deferred declaration gap is returned by wrapping the construction in a lambda in a jig.

  • If the value is an array, it is converted to a string via #join. If the property is ‘font-family’, the values are joined with a comma, otherwise a space is used.

  • Otherwise property and value are converted to strings and a CSS declaration string is returned.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/jig/css.rb', line 111

def declaration(property, value)
  case value
  when nil, false
    ""
  when Symbol
    Gap.new(value) { |fill| declaration(property, fill) }
  when Gap
    value
  when Jig
    Jig.new { declaration(property, value.to_s) }
  when Proc, Method
    Jig.new { declaration(property, value.call) }
  when Array
    seperator = (property == 'font[-_]family' ? ", " : " ")
    declaration(property, value.join(seperator))
  else
    property.to_s =~ /\A(.*[^!])(!?)\z/
    property = $1.to_s.tr('_','-')
    "#{property}: #{value}#{" !important" unless $2.empty?}; "
  end
end

#declarationsObject

Extract the declaration list from the rule. The list is returned as a jig and not as a hash.

div(:color => 'red').declarations   # => Jig["color: red; ", :__de]


247
248
249
# File 'lib/jig/css.rb', line 247

def declarations
  slice(index(:__ds)+1..index(:__de)-1)
end

#lang(lang) ⇒ Object

Construct a lang pseudo class.



202
203
204
# File 'lib/jig/css.rb', line 202

def lang(lang)
  before(:__s, ":lang(#{lang})")
end

#merge(other) ⇒ Object Also known as: |

Merge this rule with another object.

  • If the other object is a hash, the hash is converted to a CSS declaration list and merged with the current list.

  • If the other object is a rule, the other selectors and declarations are merged with the current selectors and declarations.

  • Any other object is assumed to be a selector string and is merged with the current selectors.

C.div.merge(:color => ‘red’) # => div { color: red; } C.div.merge(C.h1) # => div, h1 {} C.div(:color => ‘blue’).merge(C.h1(:font_size => ‘10pt’))

# => div, h1 { color: blue; font-size: 10pt }

C.div.merge(‘h1, h2, h3’) # => div, h1, h2, h3 {}



220
221
222
223
224
225
226
227
228
229
230
# File 'lib/jig/css.rb', line 220

def merge(other)
  return self unless other
  case other
  when Hash
    before(:__de, to_declarations(other)) 
  when self.class
    before(:__s, ", ", other.selector).before(:__de, other.declarations)
  else
    before(:__s, ", ", other)
  end
end

#nth_child(a = 0, b = 0) ⇒ Object

Construct a nth_child pseudo class.



182
183
184
# File 'lib/jig/css.rb', line 182

def nth_child(a=0,b=0)
  before(:__s, ":nth-child(#{a}n+#{b})")
end

#nth_last_child(a = 0, b = 0) ⇒ Object

Construct a nth_last_child pseudo class.



187
188
189
# File 'lib/jig/css.rb', line 187

def nth_last_child(a=0,b=0)
  before(:__s, ":nth-last-child(#{a}n+#{b})")
end

#nth_last_of_type(a = 0, b = 0) ⇒ Object

Construct a nth-last-of-type pseudo class.



197
198
199
# File 'lib/jig/css.rb', line 197

def nth_last_of_type(a=0,b=0)
  before(:__s, ":nth-last-of-type(#{a}n+#{b})")
end

#nth_of_type(a = 0, b = 0) ⇒ Object

Construct a nth-of-type pseudo class.



192
193
194
# File 'lib/jig/css.rb', line 192

def nth_of_type(a=0,b=0)
  before(:__s, ":nth-of-type(#{a}n+#{b})")
end

#selectorObject

Extract the selector list from the rule as a jig.

(div | h1).selector     # => Jig["div, h1"]


240
241
242
# File 'lib/jig/css.rb', line 240

def selector
  slice(0...index(:__s))
end

#to_declarations(hash) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/jig/css.rb', line 80

def to_declarations(hash)
  return nil unless hash
  hash.inject(Jig.null) do |djig, (property, value)| 
    djig.push(
      case value
        when Gap
          value
        when Symbol
          Gap.new(value) { |fill| declaration(property, fill) }
        else
          declaration(property, value)
      end
    )
  end
end

#to_jigObject



232
233
234
# File 'lib/jig/css.rb', line 232

def to_jig
  Jig.new(plug( :__s => nil, :__de => nil, :__ds => nil ))
end

#~(other) ⇒ Object

Construct a general sibling selector. The first sibling is the lhs selector and the other sibling is rhs selector.

div ~ p     # => "div ~ p {}"


150
151
152
# File 'lib/jig/css.rb', line 150

def ~(other)
  before(:__s, "~", other.selector).before(:__de, other.declarations)
end