class Sass::CSS

namely converting CSS documents to Sass templates.
This class contains the functionality used in the css2sass utility,

def assert_match(re)

def assert_match(re)
  if !@template.scan(re)
    line = @template.string[0..@template.pos].count "\n"
    # Display basic regexps as plain old strings
    expected = re.source == Regexp.escape(re.source) ? "\"#{re.source}\"" : re.inspect
    raise Exception.new("Invalid CSS on line #{line}: expected #{expected}")
  end
  whitespace
end

def attributes(rule)

def attributes(rule)
  while @template.scan(/[^:\}\s]+/)
    name = @template[0]
    whitespace
    assert_match /:/
    value = ''
    while @template.scan(/[^;\s\}]+/)
      value << @template[0] << whitespace
    end
    assert_match /(;|(?=\}))/
    rule << Tree::AttrNode.new(name, value, nil)
  end
  assert_match /\}/
end

def build_tree

def build_tree
  root = Tree::Node.new(nil)
  whitespace
  directives         root
  rules              root
  expand_commas      root
  parent_ref_rules   root
  remove_parent_refs root
  flatten_rules      root
  fold_commas        root
  root
end

def directives(root)

def directives(root)
  while @template.scan(/@/)
    name = @template.scan /[^\s;]+/
    whitespace
    value = @template.scan /[^;]+/
    assert_match /;/
    whitespace
    if name == "import" && value =~ /^(url\()?"?([^\s\(\)\"]+)\.css"?\)?$/
      value = $2
    end
    root << Tree::ValueNode.new("@#{name} #{value};", nil)
  end
end

def expand_commas(root)

but it's necessary to get nesting to work properly.
Yes, this expands the amount of code,

color: blue
baz
color: blue
bar
color: blue
foo

into

color: blue
foo, bar, baz

Transform
def expand_commas(root)
  root.children.map! do |child|
    next child unless Tree::RuleNode === child && child.rule.include?(',')
    child.rule.split(',').map do |rule|
      node = Tree::RuleNode.new(rule, nil)
      node.children = child.children
      node
    end
  end
  root.children.flatten!
end

def flatten_rule(rule)

def flatten_rule(rule)
  while rule.children.size == 1 && rule.children.first.is_a?(Tree::RuleNode)
    child = rule.children.first
    if child.rule[0] == ?&
      rule.rule = child.rule.gsub /^&/, rule.rule
    else
      rule.rule = "#{rule.rule} #{child.rule}"
    end
    rule.children = child.children
  end
  flatten_rules(rule)
end

def flatten_rules(root)


color: blue
foo.bar

becomes

color: blue
&.bar
foo

and

color: red
foo bar baz

becomes

color: red
baz
bar
foo

Flatten rules so that
def flatten_rules(root)
  root.children.each { |child| flatten_rule(child) if child.is_a?(Tree::RuleNode) }
end

def fold_commas(root)


color: blue
bar, baz
foo

into

color: blue
baz
color: blue
bar
foo

Transform
def fold_commas(root)
  prev_rule = nil
  root.children.map! do |child|
    next child unless Tree::RuleNode === child
    if prev_rule && prev_rule.children == child.children
      prev_rule.rule << ", #{child.rule}"
      next nil
    end
    fold_commas(child)
    prev_rule = child
    child
  end
  root.children.compact!
end

def initialize(template, options = {})

to a Sass string when +render+ is called.
Creates a new instance of Sass::CSS that will compile the given document
def initialize(template, options = {})
  if template.is_a? IO
    template = template.read
  end
  @options = options
  @template = StringScanner.new(template)
end

def parent_ref_rules(root)


color: blue
& baz
color: red
& bar
color: green
foo

becomes

color: blue
foo baz
color: red
foo bar
color: green
foo

so that
This has the side effect of nesting rules,

color: blue
&.bar
color: green
foo

becomes

color: blue
foo.bar
color: green
foo

Make rules use parent refs so that
def parent_ref_rules(root)
  rules = OrderedHash.new
  root.children.select { |c| Tree::RuleNode === c }.each do |child|
    root.children.delete child
    first, rest = child.rule.scan(/^(&?(?: .|[^ ])[^.#: \[]*)([.#: \[].*)?$/).first
    rules[first] ||= Tree::RuleNode.new(first, nil)
    if rest
      child.rule = "&" + rest
      rules[first] << child
    else
      rules[first].children += child.children
    end
  end
  rules.values.each { |v| parent_ref_rules(v) }
  root.children += rules.values
end

def remove_parent_refs(root)


color: blue
bar
foo

becomes

color: blue
& bar
foo

Remove useless parent refs so that
def remove_parent_refs(root)
  root.children.each do |child|
    if child.is_a?(Tree::RuleNode)
      child.rule.gsub! /^& /, ''
      remove_parent_refs child
    end
  end
end

def render

containing the CSS template.
Processes the document and returns the result as a string
def render
  begin
    build_tree.to_sass(@options).lstrip
  rescue Exception => err
    line = @template.string[0...@template.pos].split("\n").size
    err.backtrace.unshift "(css):#{line}"
    raise err
  end
end

def rules(root)

def rules(root)
  rules = []
  while @template.scan(/[^\{\s]+/)
    rules << @template[0]
    whitespace
    if @template.scan(/\{/)
      result = Tree::RuleNode.new(rules.join(' '), nil)
      root << result
      rules = []
      whitespace
      attributes(result)
    end
  end
end

def whitespace

def whitespace
  space = @template.scan(/\s*/) || ''
  # If we've hit a comment,
  # go past it and look for more whitespace
  if @template.scan(/\/\*/)
    @template.scan_until(/\*\//)
    return space + whitespace
  end
  return space
end