Class: Sass::Tree::Visitors::Cssize

Inherits:
Base
  • Object
show all
Defined in:
lib/sass/tree/visitors/cssize.rb

Overview

A visitor for converting a static Sass tree into a static CSS tree.

Constant Summary

Constants inherited from Base

Base::NODE_NAME_RE

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#node_name, #visit_if

Constructor Details

#initializeCssize (protected)

Returns a new instance of Cssize.



14
15
16
# File 'lib/sass/tree/visitors/cssize.rb', line 14

def initialize
  @extends = Sass::Util::SubsetMap.new
end

Instance Attribute Details

#parentTree::Node (readonly, protected)

Returns the immediate parent of the current node.

Returns:



12
13
14
# File 'lib/sass/tree/visitors/cssize.rb', line 12

def parent
  @parent
end

Class Method Details

.visit(root) ⇒ (Tree::Node, Sass::Util::SubsetMap)

Returns The resulting tree of static nodes and the extensions defined for this tree.

Parameters:

  • root (Tree::Node)

    The root node of the tree to visit.

Returns:



6
# File 'lib/sass/tree/visitors/cssize.rb', line 6

def self.visit(root); super; end

Instance Method Details

#visit(node) (protected)

If an exception is raised, this adds proper metadata to the backtrace.



19
20
21
22
23
24
# File 'lib/sass/tree/visitors/cssize.rb', line 19

def visit(node)
  super(node.dup)
rescue Sass::SyntaxError => e
  e.modify_backtrace(:filename => node.filename, :line => node.line)
  raise e
end

#visit_children(parent) (protected)

Keeps track of the current parent node.



27
28
29
30
31
32
# File 'lib/sass/tree/visitors/cssize.rb', line 27

def visit_children(parent)
  with_parent parent do
    parent.children = super.flatten
    parent
  end
end

#visit_extend(node) (protected)

Registers an extension in the @extends subset map.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/sass/tree/visitors/cssize.rb', line 70

def visit_extend(node)
  node.resolved_selector.members.each do |seq|
    if seq.members.size > 1
      raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: can't extend nested selectors")
    end

    sseq = seq.members.first
    if !sseq.is_a?(Sass::Selector::SimpleSequence)
      raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: invalid selector")
    end

    sel = sseq.members
    parent.resolved_rules.members.each do |seq|
      if !seq.members.last.is_a?(Sass::Selector::SimpleSequence)
        raise Sass::SyntaxError.new("#{seq} can't extend: invalid selector")
      end

      @extends[sel] = seq
    end
  end

  []
end

#visit_import(node) (protected)

Modifies exception backtraces to include the imported file.



95
96
97
98
99
100
101
102
# File 'lib/sass/tree/visitors/cssize.rb', line 95

def visit_import(node)
  # Don't use #visit_children to avoid adding the import node to the list of parents.
  node.children.map {|c| visit(c)}.flatten
rescue Sass::SyntaxError => e
  e.modify_backtrace(:filename => node.children.first.filename)
  e.add_backtrace(:filename => node.filename, :line => node.line)
  raise e
end

#visit_media(node) (protected)

Bubbles the @media directive up through RuleNodes and merges it with other @media directives.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/sass/tree/visitors/cssize.rb', line 106

def visit_media(node)
  if parent.is_a?(Sass::Tree::RuleNode)
    new_rule = parent.dup
    new_rule.children = node.children
    node.children = with_parent(node) {Array(visit(new_rule))}
    # If the last child is actually the end of the group,
    # the parent's cssize will set it properly
    node.children.last.group_end = false unless node.children.empty?
  else
    yield
  end

  media = node.children.select {|c| c.is_a?(Sass::Tree::MediaNode)}
  node.children.reject! {|c| c.is_a?(Sass::Tree::MediaNode)}
  media.each do |n|
    n.query = node.query.map {|pq| n.query.map {|cq| "#{pq} and #{cq}"}}.flatten
  end
  (node.children.empty? ? [] : [node]) + media
end

#visit_mixin(node) (protected)

Asserts that all the mixin's children are valid in their new location.



127
128
129
130
131
132
133
134
# File 'lib/sass/tree/visitors/cssize.rb', line 127

def visit_mixin(node)
  # Don't use #visit_children to avoid adding the mixin node to the list of parents.
  node.children.map {|c| visit(c)}.flatten
rescue Sass::SyntaxError => e
  e.modify_backtrace(:mixin => node.name, :filename => node.filename, :line => node.line)
  e.add_backtrace(:filename => node.filename, :line => node.line)
  raise e
end

#visit_prop(node) (protected)

Converts nested properties into flat properties and updates the indentation of the prop node based on the nesting level.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/sass/tree/visitors/cssize.rb', line 138

def visit_prop(node)
  if parent.is_a?(Sass::Tree::PropNode)
    node.resolved_name = "#{parent.resolved_name}-#{node.resolved_name}"
    node.tabs = parent.tabs + (parent.resolved_value.empty? ? 0 : 1) if node.style == :nested
  end

  yield

  result = node.children.dup
  if !node.resolved_value.empty? || node.children.empty?
    node.send(:check!)
    result.unshift(node)
  end

  result
end

#visit_root(node) ⇒ (Tree::Node, Sass::Util::SubsetMap) (protected)

In Ruby 1.8, ensures that there's only one @charset directive and that it's at the top of the document.

Returns:



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/sass/tree/visitors/cssize.rb', line 52

def visit_root(node)
  yield

  # In Ruby 1.9 we can make all @charset nodes invisible
  # and infer the final @charset from the encoding of the final string.
  if Sass::Util.ruby1_8? && parent.nil?
    charset = node.children.find {|c| c.is_a?(Sass::Tree::CharsetNode)}
    node.children.reject! {|c| c.is_a?(Sass::Tree::CharsetNode)}
    node.children.unshift charset if charset
  end

  return node, @extends
rescue Sass::SyntaxError => e
  e.sass_template ||= node.template
  raise e
end

#visit_rule(node) (protected)

Resolves parent references and nested selectors, and updates the indentation of the rule node based on the nesting level.



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/sass/tree/visitors/cssize.rb', line 157

def visit_rule(node)
  parent_resolved_rules = parent.is_a?(Sass::Tree::RuleNode) ? parent.resolved_rules : nil
  # It's possible for resolved_rules to be set if we've duplicated this node during @media bubbling
  node.resolved_rules ||= node.parsed_rules.resolve_parent_refs(parent_resolved_rules)

  yield

  rules = node.children.select {|c| c.is_a?(Sass::Tree::RuleNode) || c.is_a?(Sass::Tree::MediaNode)}
  props = node.children.reject {|c| c.is_a?(Sass::Tree::RuleNode) || c.is_a?(Sass::Tree::MediaNode) || c.invisible?}

  unless props.empty?
    node.children = props
    rules.each {|r| r.tabs += 1} if node.style == :nested
    rules.unshift(node)
  end

  rules.last.group_end = true unless parent.is_a?(Sass::Tree::RuleNode) || rules.empty?

  rules
end

#with_parent(parent) { ... } ⇒ Object (protected)

Runs a block of code with the current parent node replaced with the given node.

Parameters:

  • parent (Tree::Node)

    The new parent for the duration of the block.

Yields:

  • A block in which the parent is set to parent.

Returns:

  • (Object)

    The return value of the block.



40
41
42
43
44
45
# File 'lib/sass/tree/visitors/cssize.rb', line 40

def with_parent(parent)
  old_parent, @parent = @parent, parent
  yield
ensure
  @parent = old_parent
end