Class: Less::Node::Element

Inherits:
Object show all
Includes:
Enumerable, Entity
Defined in:
lib/less/engine/nodes/element.rb

Overview

Element

div …

TODO: Look into making @rules its own hash-like class TODO: Look into whether selector should be child by default

Instance Attribute Summary collapse

Attributes included from Entity

#parent

Instance Method Summary collapse

Methods included from Entity

#path, #root

Constructor Details

#initialize(name = "", selector = '') ⇒ Element

Returns a new instance of Element.



18
19
20
21
22
23
# File 'lib/less/engine/nodes/element.rb', line 18

def initialize name = "", selector = ''
  @name = name
  @set = []
  @rules = [] # Holds all the nodes under this element's hierarchy
  @selector = Selector[selector.strip].new  # descendant | child | adjacent
end

Instance Attribute Details

#fileObject

Returns the value of attribute file.



15
16
17
# File 'lib/less/engine/nodes/element.rb', line 15

def file
  @file
end

#nameObject

Returns the value of attribute name.



15
16
17
# File 'lib/less/engine/nodes/element.rb', line 15

def name
  @name
end

#rulesObject

Returns the value of attribute rules.



15
16
17
# File 'lib/less/engine/nodes/element.rb', line 15

def rules
  @rules
end

#selectorObject

Returns the value of attribute selector.



15
16
17
# File 'lib/less/engine/nodes/element.rb', line 15

def selector
  @selector
end

#setObject

Returns the value of attribute set.



15
16
17
# File 'lib/less/engine/nodes/element.rb', line 15

def set
  @set
end

Instance Method Details

#<<(obj) ⇒ Object

Add an arbitrary node to this element



124
125
126
127
128
129
130
131
# File 'lib/less/engine/nodes/element.rb', line 124

def << obj
  if obj.kind_of? Node::Entity
    obj.parent = self
    @rules << obj
  else
    raise ArgumentError, "argument can't be a #{obj.class}"
  end
end

#==(other) ⇒ Object



93
94
95
# File 'lib/less/engine/nodes/element.rb', line 93

def == other
  name == other.name
end

#[](key) ⇒ Object

Select a child element TODO: Implement full selector syntax & merge with descend()



83
84
85
86
87
88
89
90
91
# File 'lib/less/engine/nodes/element.rb', line 83

def [] key
  case key
    when Entity
      @rules.find {|i| i.eql? key }
    when ::String
      @rules.find {|i| i.to_s == key }
    else raise ArgumentError
  end
end

#class?Boolean

Returns:

  • (Boolean)


25
# File 'lib/less/engine/nodes/element.rb', line 25

def class?;     name =~ /^\./ end

#descend(selector, element) ⇒ Object

Same as above, except with a specific selector TODO: clean this up or implement it differently



110
111
112
113
114
115
116
117
118
119
# File 'lib/less/engine/nodes/element.rb', line 110

def descend selector, element
  if selector.is_a? Child
    s = self[element.name].selector
    self[element.name] if s.is_a? Child or s.is_a? Descendant
  elsif selector.is_a? Descendant
    self[element.name]
  else
    self[element.name] if self[element.name].selector.class == selector.class
  end
end

#each(path = [], &blk) ⇒ Object

Traverse the whole tree, returning each leaf (recursive)



175
176
177
178
179
180
181
182
183
# File 'lib/less/engine/nodes/element.rb', line 175

def each path = [], &blk
  elements.each do |element|
    path << element
    yield element, path if element.leaf?
    element.each path, &blk
    path.pop
  end
  self
end

#elementsObject



79
# File 'lib/less/engine/nodes/element.rb', line 79

def elements;    @rules.select {|r| r.instance_of? Element  } end

#empty?Boolean

Returns:

  • (Boolean)


38
39
40
# File 'lib/less/engine/nodes/element.rb', line 38

def empty?
  @rules.empty?
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/less/engine/nodes/element.rb', line 97

def eql? other
  super and self.equiv? other
end

#equiv?(other) ⇒ Boolean

Returns:

  • (Boolean)


101
102
103
104
105
106
# File 'lib/less/engine/nodes/element.rb', line 101

def equiv? other
  rules.size == other.rules.size and
  !rules.zip(other.rules).map do |a, b|
    a.to_css == b.to_css
  end.include?(false)
end

#firstObject



134
# File 'lib/less/engine/nodes/element.rb', line 134

def first; elements.first end

#groupObject

Group similar rulesets together This is horrible, horrible code, but it’ll have to do until I find a proper way to do it.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/less/engine/nodes/element.rb', line 50

def group
  matched = false
  stack, result = elements.dup, []
  return self unless elements.size > 1

  elements.each do
    e = stack.first
    result << e unless matched

    matched = stack[1..-1].each do |ee|
      if e.equiv? ee and e.elements.size == 0
        self[e].set << ee
        stack.shift
      else
        stack.shift
        break false
      end
    end if stack.size > 1
  end
  @rules -= (elements - result)
  self
end

#id?Boolean

Returns:

  • (Boolean)


26
# File 'lib/less/engine/nodes/element.rb', line 26

def id?;        name =~ /^#/  end

#identifiersObject

Accessors for the different nodes in @rules



76
# File 'lib/less/engine/nodes/element.rb', line 76

def identifiers; @rules.select {|r| r.kind_of?     Property } end

#inspect(depth = 0) ⇒ Object



185
186
187
188
189
190
191
192
193
194
195
# File 'lib/less/engine/nodes/element.rb', line 185

def inspect depth = 0
  indent = lambda {|i| '.  ' * i }
  put    = lambda {|ary| ary.map {|i| indent[ depth + 1 ] + i.inspect } * "\n"}

  (root?? "\n" : "") + [
    indent[ depth ] + self.to_s,
    put[ properties ],
    put[ variables ],
    elements.map {|i| i.inspect( depth + 1 ) } * "\n"
  ].reject(&:empty?).join("\n") + "\n" + indent[ depth ]
end

#lastObject



133
# File 'lib/less/engine/nodes/element.rb', line 133

def last;  elements.last  end

#leaf?Boolean

Returns:

  • (Boolean)


42
43
44
# File 'lib/less/engine/nodes/element.rb', line 42

def leaf?
  elements.empty?
end

#nearest(ident) ⇒ Object

Find the nearest variable in the hierarchy or raise a NameError



163
164
165
166
167
168
169
170
# File 'lib/less/engine/nodes/element.rb', line 163

def nearest ident
  ary = ident =~ /^[.#]/ ? :elements : :variables
  path.map do |node|
    node.send(ary).find {|i| i.to_s == ident }
  end.compact.first.tap do |result|
    raise VariableNameError, ident unless result
  end
end

#propertiesObject



77
# File 'lib/less/engine/nodes/element.rb', line 77

def properties;  @rules.select {|r| r.instance_of? Property } end

#root?Boolean

Top-most node?

Returns:

  • (Boolean)


34
35
36
# File 'lib/less/engine/nodes/element.rb', line 34

def root?
  parent.nil?
end

#tag?Boolean

Returns:

  • (Boolean)


29
30
31
# File 'lib/less/engine/nodes/element.rb', line 29

def tag?
  not id? || class? || universal?
end

#to_css(path = []) ⇒ Object

Entry point for the css conversion



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/less/engine/nodes/element.rb', line 140

def to_css path = []
  path << @selector.to_css << name unless root?

  content = properties.map do |i|
    ' ' * 2 + i.to_css
  end.compact.reject(&:empty?) * "\n"

  content = content.include?("\n") ?
    "\n#{content}\n" : " #{content.strip} "
  ruleset = !content.strip.empty??
    "#{[path.reject(&:empty?).join.strip,
    *@set.map(&:name)].uniq * ', '} {#{content}}\n" : ""

  css = ruleset + elements.map do |i|
    i.to_css(path)
  end.reject(&:empty?).join
  path.pop; path.pop
  css
end

#to_sObject



135
# File 'lib/less/engine/nodes/element.rb', line 135

def to_s; root?? '*' : name end

#universal?Boolean

Returns:

  • (Boolean)


27
# File 'lib/less/engine/nodes/element.rb', line 27

def universal?; name == '*'   end

#variablesObject



78
# File 'lib/less/engine/nodes/element.rb', line 78

def variables;   @rules.select {|r| r.instance_of? Variable } end