Permalink
Browse files

Restructure a sass tree for all the nodes that bubble up

  • Loading branch information...
1 parent 68cf28e commit b540a68d30e22d631f2d0a11dd5d42594197079d @chriseppstein committed Sep 22, 2010
Showing with 70 additions and 1 deletion.
  1. +59 −0 lib/sass/tree/node.rb
  2. +11 −1 lib/sass/tree/root_node.rb
View
@@ -259,6 +259,57 @@ def _around_dump
options = old_options
end
+ # Restructures a static Sass tree (e.g. the output of \{#perform})
+ # into another static Sass tree. This allows a single node in the
+ # tree to rewrite itself as an array of nodes that should replace it
+ # in its parent's child array.
+ #
+ # This step is used to bubble nested nodes to the top level
+ # in cases where CSS does not understand them in a nested context.
+ #
+ # \{#restructure} shouldn't be overridden directly;
+ # instead, override \{#\_restructure} or \{#restructure!}.
+ #
+ # @return [Array<Tree::Node>] The resulting tree of static nodes
+ # @see Sass::Tree
+ # @see Sass::Tree::RootNode#restructure
+ def restructure
+ new_children = children.map {|c| c.restructure}.flatten
+ unless new_children.any?{|c| c.bubbles?(self)}
+ # optimization path?
+ self.children = new_children
+ return [self]
+ end
+ child_groups = [[]]
+ new_children.each do |child|
+ if child.bubbles?(self)
+ child_groups << [child]
+ child_groups << []
+ else
+ child_groups.last << child
+ end
+ end
+ child_groups.reject!{|group| group.empty?}
+ replacements = child_groups.map do |children|
+ node = self.dup
+ if children.size == 1 && children.first.bubbles?(self)
+ # swap the child and parent in the tree
+ node, child = children.first, node
+ child.children = node.children
+ node.children = [child]
+ else
+ node.children = children
+ end
+ node
+ end
+ replacements
+ end
+
+ # Whether this node should bubble up to the next level
+ def bubbles?(parent)
+ false
+ end
+
protected
# Computes the CSS corresponding to this particular Sass node.
@@ -276,6 +327,14 @@ def _to_s
Sass::Util.abstract(self)
end
+ # Destructively converts this static Sass node into a new static Sass node.
+ # This *does* modify this node,
+ # but will be run non-destructively by \{#\_restructure\}.
+ #
+ # @see #restructure
+ def restructure!
+ end
+
# Converts this static Sass node into a static CSS node,
# returning the new node.
# This doesn't modify this node or any of its children.
@@ -26,11 +26,21 @@ def to_s(*args)
# @see #perform
# @see #to_s
def render
- result, extends = perform(Environment.new).cssize
+ result = self.perform(Environment.new)
+ result = result.restructure
+ result, extends = result.cssize
result = result.do_extend(extends) unless extends.empty?
result.to_s
end
+ # The root node is always on the top and it needn't be restructured
+ # so it does not return an array.
+ def restructure
+ node = self.dup
+ node.children = children.map {|c| c.restructure}.flatten
+ return node
+ end
+
# @see Node#perform
def perform(environment)
environment.options = @options if environment.options.nil? || environment.options.empty?

0 comments on commit b540a68

Please sign in to comment.