Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

215 lines (190 sloc) 6.866 kb
module Sass
# A namespace for nodes in the Sass parse tree.
#
# The Sass parse tree has three states: dynamic, static Sass, and static CSS.
#
# When it's first parsed, a Sass document is in the dynamic state.
# It has nodes for mixin definitions and `@for` loops and so forth,
# in addition to nodes for CSS rules and properties.
# Nodes that only appear in this state are called **dynamic nodes**.
#
# {Tree::Visitors::Perform} creates a static Sass tree, which is different.
# It still has nodes for CSS rules and properties
# but it doesn't have any dynamic-generation-related nodes.
# The nodes in this state are in the same structure as the Sass document:
# rules and properties are nested beneath one another.
# Nodes that can be in this state or in the dynamic state
# are called **static nodes**; nodes that can only be in this state
# are called **solely static nodes**.
#
# {Tree::Visitors::Cssize} is then used to create a static CSS tree.
# This is like a static Sass tree,
# but the structure exactly mirrors that of the generated CSS.
# Rules and properties can't be nested beneath one another in this state.
#
# Finally, {Tree::Visitors::ToCss} can be called on a static CSS tree
# to get the actual CSS code as a string.
module Tree
# The abstract superclass of all parse-tree nodes.
class Node
include Enumerable
# The child nodes of this node.
#
# @return [Array<Tree::Node>]
attr_reader :children
# Whether or not this node has child nodes.
# This may be true even when \{#children} is empty,
# in which case this node has an empty block (e.g. `{}`).
#
# @return [Boolean]
attr_accessor :has_children
# The line of the document on which this node appeared.
#
# @return [Fixnum]
attr_accessor :line
# The source range in the document on which this node appeared.
#
# @return [Sass::Source::Range]
attr_accessor :source_range
# The name of the document on which this node appeared.
#
# @return [String]
attr_writer :filename
# The options hash for the node.
# See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
#
# @return [{Symbol => Object}]
attr_reader :options
def initialize
@children = []
@filename = nil
@options = nil
end
# Sets the options hash for the node and all its children.
#
# @param options [{Symbol => Object}] The options
# @see #options
def options=(options)
Sass::Tree::Visitors::SetOptions.visit(self, options)
end
# @private
def children=(children)
self.has_children ||= !children.empty?
@children = children
end
# The name of the document on which this node appeared.
#
# @return [String]
def filename
@filename || (@options && @options[:filename])
end
# Appends a child to the node.
#
# @param child [Tree::Node, Array<Tree::Node>] The child node or nodes
# @raise [Sass::SyntaxError] if `child` is invalid
def <<(child)
return if child.nil?
if child.is_a?(Array)
child.each {|c| self << c}
else
self.has_children = true
@children << child
end
end
# Compares this node and another object (only other {Tree::Node}s will be equal).
# This does a structural comparison;
# if the contents of the nodes and all the child nodes are equivalent,
# then the nodes are as well.
#
# Only static nodes need to override this.
#
# @param other [Object] The object to compare with
# @return [Boolean] Whether or not this node and the other object
# are the same
# @see Sass::Tree
def ==(other)
self.class == other.class && other.children == children
end
# True if \{#to\_s} will return `nil`;
# that is, if the node shouldn't be rendered.
# Should only be called in a static tree.
#
# @return [Boolean]
def invisible?; false; end
# The output style. See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
#
# @return [Symbol]
def style
@options[:style]
end
# Computes the CSS corresponding to this static CSS tree.
#
# @return [String] The resulting CSS
# @see Sass::Tree
def css
Sass::Tree::Visitors::ToCss.new.visit(self)
end
# Computes the CSS corresponding to this static CSS tree, along with
# the respective source map.
#
# @return [(String, Sass::Source::Map)] The resulting CSS and the source map
# @see Sass::Tree
def css_with_sourcemap
visitor = Sass::Tree::Visitors::ToCss.new(:build_source_mapping)
result = visitor.visit(self)
return result, visitor.source_mapping
end
# Returns a representation of the node for debugging purposes.
#
# @return [String]
def inspect
return self.class.to_s unless has_children
"(#{self.class} #{children.map {|c| c.inspect}.join(' ')})"
end
# Iterates through each node in the tree rooted at this node
# in a pre-order walk.
#
# @yield node
# @yieldparam node [Node] a node in the tree
def each
yield self
children.each {|c| c.each {|n| yield n}}
end
# Converts a node to Sass code that will generate it.
#
# @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize})
# @return [String] The Sass code corresponding to the node
def to_sass(options = {})
Sass::Tree::Visitors::Convert.visit(self, options, :sass)
end
# Converts a node to SCSS code that will generate it.
#
# @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize})
# @return [String] The Sass code corresponding to the node
def to_scss(options = {})
Sass::Tree::Visitors::Convert.visit(self, options, :scss)
end
# Return a deep clone of this node.
# The child nodes are cloned, but options are not.
#
# @return [Node]
def deep_copy
Sass::Tree::Visitors::DeepCopy.visit(self)
end
# Whether or not this node bubbles up through RuleNodes.
#
# @return [Boolean]
def bubbles?
false
end
protected
# @see Sass::Shared.balance
# @raise [Sass::SyntaxError] if the brackets aren't balanced
def balance(*args)
res = Sass::Shared.balance(*args)
return res if res
raise Sass::SyntaxError.new("Unbalanced brackets.", :line => line)
end
end
end
end
Jump to Line
Something went wrong with that request. Please try again.