class Sass::Tree::Visitors::Cssize

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

def self.visit(root); super; end

Returns:
  • ((Tree::Node, Sass::Util::SubsetMap)) - The resulting tree of static nodes

Parameters:
  • root (Tree::Node) -- The root node of the tree to visit.
def self.visit(root); super; end

def bubble(node)

def bubble(node)
  return unless 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?
  true
end

def initialize

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

def visit(node)

If an exception is raised, this adds proper metadata to the backtrace.
def visit(node)
  super(node)
rescue Sass::SyntaxError => e
  e.modify_backtrace(:filename => node.filename, :line => node.line)
  raise e
end

def visit_children(parent)

Keeps track of the current parent node.
def visit_children(parent)
  with_parent parent do
    parent.children = super.flatten
    parent
  end
end

def visit_extend(node)

Registers an extension in the `@extends` subset map.
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")
    elsif sseq.members.any? {|ss| ss.is_a?(Sass::Selector::Parent)}
      raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: can't extend parent selectors")
    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

def visit_import(node)

Modifies exception backtraces to include the imported file.
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

def visit_media(node)

and merges it with other `@media` directives.
Bubbles the `@media` directive up through RuleNodes
def visit_media(node)
  yield unless bubble(node)
  media = node.children.select {|c| c.is_a?(Sass::Tree::MediaNode)}
  node.children.reject! {|c| c.is_a?(Sass::Tree::MediaNode)}
  media = media.select {|n| n.query = n.query.merge(node.query)}
  (node.children.empty? ? [] : [node]) + media
end

def visit_prop(node)

and updates the indentation of the prop node based on the nesting level.
Converts nested properties into flat properties
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

def visit_root(node)

Returns:
  • ((Tree::Node, Sass::Util::SubsetMap)) - The resulting tree of static nodes
def visit_root(node)
  yield
  if parent.nil?
    # 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?
      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
    imports = Sass::Util.extract!(node.children) do |c|
      c.is_a?(Sass::Tree::DirectiveNode) && !c.is_a?(Sass::Tree::MediaNode) &&
        c.resolved_value =~ /^@import /i
    end
    charset_and_index = Sass::Util.ruby1_8? &&
      node.children.each_with_index.find {|c, _| c.is_a?(Sass::Tree::CharsetNode)}
    if charset_and_index
      index = charset_and_index.last
      node.children = node.children[0..index] + imports + node.children[index+1..-1]
    else
      node.children = imports + node.children
    end
  end
  return node, @extends
rescue Sass::SyntaxError => e
  e.sass_template ||= node.template
  raise e
end

def visit_rule(node)

and updates the indentation of the rule node based on the nesting level.
Resolves parent references and nested selectors,
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.bubbles?}
  props = node.children.reject {|c| c.is_a?(Sass::Tree::RuleNode) || c.bubbles? || 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

def visit_supports(node)

Bubbles the `@supports` directive up through RuleNodes.
def visit_supports(node)
  yield unless bubble(node)
  node
end

def visit_trace(node)

Asserts that all the traced children are valid in their new location.
def visit_trace(node)
  # Don't use #visit_children to avoid adding the trace 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

def with_parent(parent)

Returns:
  • (Object) - The return value of the block.

Other tags:
    Yield: - A block in which the parent is set to `parent`.

Parameters:
  • parent (Tree::Node) -- The new parent for the duration of the block.
def with_parent(parent)
  old_parent, @parent = @parent, parent
  yield
ensure
  @parent = old_parent
end