Class: Sass::Tree::Node

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/sass/tree/node.rb

Overview

The abstract superclass of all parse-tree nodes.

Constant Summary collapse

SAVED_OPTIONS =

Names of options that are saved when the node is serialized and cached.

[:importer]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeNode

Returns a new instance of Node.



59
60
61
# File 'lib/sass/tree/node.rb', line 59

def initialize
  @children = []
end

Instance Attribute Details

#childrenArray<Tree::Node>

The child nodes of this node.

Returns:



34
35
36
# File 'lib/sass/tree/node.rb', line 34

def children
  @children
end

#filenameString

The name of the document on which this node appeared.

Returns:

  • (String)


81
82
83
# File 'lib/sass/tree/node.rb', line 81

def filename
  @filename || (@options && @options[:filename])
end

#has_childrenBoolean

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. {}).

Returns:

  • (Boolean)


41
42
43
# File 'lib/sass/tree/node.rb', line 41

def has_children
  @has_children
end

#lineFixnum

The line of the document on which this node appeared.

Returns:

  • (Fixnum)


46
47
48
# File 'lib/sass/tree/node.rb', line 46

def line
  @line
end

#options{Symbol => Object}

The options hash for the node. See the Sass options documentation.

Returns:

  • ({Symbol => Object})


57
58
59
# File 'lib/sass/tree/node.rb', line 57

def options
  @options
end

Instance Method Details

#<<(child)

Appends a child to the node.

Parameters:

Raises:

See Also:



90
91
92
93
94
95
96
97
98
99
# File 'lib/sass/tree/node.rb', line 90

def <<(child)
  return if child.nil?
  if child.is_a?(Array)
    child.each {|c| self << c}
  else
    check_child! child
    self.has_children = true
    @children << child
  end
end

#==(other) ⇒ Boolean

Compares this node and another object (only other Sass::Tree::Nodes 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.

Parameters:

  • other (Object)

    The object to compare with

Returns:

  • (Boolean)

    Whether or not this node and the other object are the same

See Also:



123
124
125
# File 'lib/sass/tree/node.rb', line 123

def ==(other)
  self.class == other.class && other.children == children
end

#_around_dump

Ensures that only SAVED_OPTIONS get saved.



251
252
253
254
255
256
257
258
259
260
# File 'lib/sass/tree/node.rb', line 251

def _around_dump
  old_options = @options
  @options = {}
  SAVED_OPTIONS.each do |opt|
    @options[opt] = old_options[opt]
  end
  yield
ensure
  options = old_options
end

#_cssize(extends, parent) ⇒ Tree::Node+ (protected)

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.

Parameters:

Returns:

Raises:

See Also:



291
292
293
294
295
# File 'lib/sass/tree/node.rb', line 291

def _cssize(extends, parent)
  node = dup
  node.cssize!(extends, parent)
  node
end

#_perform(environment) ⇒ Tree::Node+ (protected)

Runs any dynamic Sass code in this particular node. This doesn't modify this node or any of its children.

Parameters:

  • environment (Sass::Environment)

    The lexical environment containing variable and mixin values

Returns:

See Also:



318
319
320
321
322
# File 'lib/sass/tree/node.rb', line 318

def _perform(environment)
  node = dup
  node.perform!(environment)
  node
end

#_to_sString? (protected)

Computes the CSS corresponding to this particular Sass node.

This method should never raise SyntaxErrors. Such errors will not be properly annotated with Sass backtrace information. All error conditions should be checked in earlier transformations, such as #cssize and #perform.

Parameters:

  • args (Array)

    ignored

Returns:

  • (String, nil)

    The resulting CSS

See Also:



275
276
277
# File 'lib/sass/tree/node.rb', line 275

def _to_s
  Haml::Util.abstract(self)
end

#balance(*args) (protected)

Raises:

See Also:

  • Haml::Shared.balance


363
364
365
366
367
# File 'lib/sass/tree/node.rb', line 363

def balance(*args)
  res = Haml::Shared.balance(*args)
  return res if res
  raise Sass::SyntaxError.new("Unbalanced brackets.", :line => line)
end

#check_child!(child)

Raises an error if the given child node is invalid.

Parameters:

Raises:

See Also:



106
107
108
109
110
# File 'lib/sass/tree/node.rb', line 106

def check_child!(child)
  if msg = invalid_child?(child)
    raise Sass::SyntaxError.new(msg, :line => child.line)
  end
end

#children_to_src(tabs, opts, fmt) ⇒ String (protected)

Converts the children of this node to a Sass or SCSS string. This will return the trailing newline for the previous line, including brackets if this is SCSS.

Parameters:

  • tabs (Fixnum)

    The amount of tabulation to use for the Sass code

  • opts ({Symbol => Object})

    An options hash (see CSS#initialize)

  • fmt (Symbol)

    :sass or :scss

Returns:

  • (String)

    The Sass or SCSS code corresponding to the children



412
413
414
415
416
417
418
# File 'lib/sass/tree/node.rb', line 412

def children_to_src(tabs, opts, fmt)
  return fmt == :sass ? "\n" : " {}\n" if children.empty?

  (fmt == :sass ? "\n" : " {\n") +
    children.map {|c| c.send("to_#{fmt}", tabs + 1, opts)}.join.rstrip +
    (fmt == :sass ? "\n" : " }\n")
end

#cssize(extends, parent = nil) ⇒ Tree::Node

Converts a static Sass tree (e.g. the output of #perform) into a static CSS tree.

#cssize shouldn't be overridden directly; instead, override #_cssize or #cssize!.

Parameters:

Returns:

  • (Tree::Node)

    The resulting tree of static nodes

Raises:

See Also:



192
193
194
195
196
197
# File 'lib/sass/tree/node.rb', line 192

def cssize(extends, parent = nil)
  _cssize(extends, (parent if parent.class == self.class))
rescue Sass::SyntaxError => e
  e.modify_backtrace(:filename => filename, :line => line)
  raise e
end

#cssize!(extends, parent) (protected)

Destructively converts this static Sass node into a static CSS node. This does modify this node, but will be run non-destructively by #_cssize.

Parameters:

See Also:



306
307
308
# File 'lib/sass/tree/node.rb', line 306

def cssize!(extends, parent)
  self.children = children.map {|c| c.cssize(extends, self)}.flatten
end

#dasherize(s, opts) ⇒ String (protected)

Convert any underscores in a string into hyphens, but only if the :dasherize option is set.

Parameters:

  • s (String)

    The string to convert

  • opts ({Symbol => Object})

    The options hash

Returns:

  • (String)

    The converted string



463
464
465
466
467
468
469
# File 'lib/sass/tree/node.rb', line 463

def dasherize(s, opts)
  if opts[:dasherize]
    s.gsub('_', '-')
  else
    s
  end
end

#do_extend(extends) ⇒ Tree::Node

TODO:

Link this to the reference documentation on @extend when such a thing exists.

Converts a static CSS tree (e.g. the output of #cssize) into another static CSS tree, with the given extensions applied to all relevant RuleNodes.

Parameters:

Returns:

  • (Tree::Node)

    The resulting tree of static CSS nodes.

Raises:

  • (Sass::SyntaxError)

    Only if there's a programmer error and this is not a static CSS tree



170
171
172
173
174
175
176
177
# File 'lib/sass/tree/node.rb', line 170

def do_extend(extends)
  node = dup
  node.children = children.map {|c| c.do_extend(extends)}
  node
rescue Sass::SyntaxError => e
  e.modify_backtrace(:filename => filename, :line => line)
  raise e
end

#each {|node| ... }

Iterates through each node in the tree rooted at this node in a pre-order walk.

Yields:

  • node

Yield Parameters:

  • node (Node)

    a node in the tree



224
225
226
227
# File 'lib/sass/tree/node.rb', line 224

def each(&block)
  yield self
  children.each {|c| c.each(&block)}
end

#invalid_child?(child) ⇒ Boolean, String (protected)

Returns an error message if the given child node is invalid, and false otherwise.

By default, all child nodes except those only allowed under specific nodes (MixinDefNode, ImportNode, ExtendNode) are valid. This is expected to be overriden by subclasses for which some children are invalid.

Parameters:

Returns:

  • (Boolean, String)

    Whether or not the child node is valid, as well as the error message to display if it is invalid



380
381
382
383
384
385
386
387
388
389
# File 'lib/sass/tree/node.rb', line 380

def invalid_child?(child)
  case child
  when Tree::MixinDefNode
    "Mixins may only be defined at the root of a document."
  when Tree::ImportNode
    "Import directives may only be used at the root of a document."
  when Tree::ExtendNode
    "Extend directives may only be used within rules."
  end
end

#invisible?Boolean

True if #to_s will return nil; that is, if the node shouldn't be rendered. Should only be called in a static tree.

Returns:

  • (Boolean)


132
# File 'lib/sass/tree/node.rb', line 132

def invisible?; false; end

#perform(environment) ⇒ Tree::Node

Converts a dynamic tree into a static Sass tree. That is, runs the dynamic Sass code: mixins, variables, control directives, and so forth. This doesn't modify this node or any of its children.

#perform shouldn't be overridden directly; instead, override #_perform or #perform!.

Parameters:

  • environment (Sass::Environment)

    The lexical environment containing variable and mixin values

Returns:

  • (Tree::Node)

    The resulting tree of static nodes

Raises:

See Also:



212
213
214
215
216
217
# File 'lib/sass/tree/node.rb', line 212

def perform(environment)
  _perform(environment)
rescue Sass::SyntaxError => e
  e.modify_backtrace(:filename => filename, :line => line)
  raise e
end

#perform!(environment) (protected)

Destructively runs dynamic Sass code in this particular node. This does modify this node, but will be run non-destructively by #_perform.

Parameters:

  • environment (Sass::Environment)

    The lexical environment containing variable and mixin values

See Also:



331
332
333
# File 'lib/sass/tree/node.rb', line 331

def perform!(environment)
  self.children = perform_children(Environment.new(environment))
end

#perform_children(environment) ⇒ Array<Tree::Node> (protected)

Non-destructively runs #perform on all children of the current node.

Parameters:

  • environment (Sass::Environment)

    The lexical environment containing variable and mixin values

Returns:

  • (Array<Tree::Node>)

    The resulting static nodes



340
341
342
# File 'lib/sass/tree/node.rb', line 340

def perform_children(environment)
  children.map {|c| c.perform(environment)}.flatten
end

#run_interp(text, environment) ⇒ String (protected)

Replaces SassScript in a chunk of text with the resulting value.

Parameters:

Returns:

  • (String)

    The interpolated text



351
352
353
354
355
356
357
358
359
# File 'lib/sass/tree/node.rb', line 351

def run_interp(text, environment)
  text.map do |r|
    next r if r.is_a?(String)
    val = r.perform(environment)
    # Interpolated strings should never render with quotes
    next val.value if val.is_a?(Sass::Script::String)
    val.to_s
  end.join.strip
end

#selector_to_sass(sel, opts) ⇒ String (protected)

Converts a selector to a Sass string.

Parameters:

Returns:

  • (String)

    The Sass code corresponding to the selector



436
437
438
439
440
441
442
443
444
# File 'lib/sass/tree/node.rb', line 436

def selector_to_sass(sel, opts)
  sel.map do |r|
    if r.is_a?(String)
      r.gsub(/(,[ \t]*)?\n\s*/) {$1 ? $1 + "\n" : " "}
    else
      "\#{#{r.to_sass(opts)}}"
    end
  end.join
end

#selector_to_scss(sel, tabs, opts) ⇒ String (protected)

Converts a selector to a SCSS string.

Parameters:

  • sel (Array<String, Sass::Script::Node>)

    The selector to convert

  • tabs (Fixnum)

    The indentation of the selector

  • opts ({Symbol => Object})

    An options hash (see CSS#initialize)

Returns:

  • (String)

    The SCSS code corresponding to the selector



452
453
454
455
# File 'lib/sass/tree/node.rb', line 452

def selector_to_scss(sel, tabs, opts)
  sel.map {|r| r.is_a?(String) ? r : "\#{#{r.to_sass(opts)}}"}.
    join.gsub(/^[ \t]*/, '  ' * tabs)
end

#selector_to_src(sel, tabs, opts, fmt) ⇒ String (protected)

Converts a selector to a Sass or SCSS string.

Parameters:

  • sel (Array<String, Sass::Script::Node>)

    The selector to convert

  • tabs (Fixnum)

    The indentation of the selector

  • opts ({Symbol => Object})

    An options hash (see CSS#initialize)

  • fmt (Symbol)

    :sass or :scss

Returns:

  • (String)

    The Sass or SCSS code corresponding to the selector



427
428
429
# File 'lib/sass/tree/node.rb', line 427

def selector_to_src(sel, tabs, opts, fmt)
  fmt == :sass ? selector_to_sass(sel, opts) : selector_to_scss(sel, tabs, opts)
end

#semi(fmt) ⇒ String (protected)

Returns a semicolon if this is SCSS, or an empty string if this is Sass.

Parameters:

  • fmt (Symbol)

    :sass or :scss

Returns:

  • (String)

    A semicolon or the empty string



475
476
477
# File 'lib/sass/tree/node.rb', line 475

def semi(fmt)
  fmt == :sass ? "" : ";"
end

#styleSymbol

The output style. See the Sass options documentation.

Returns:

  • (Symbol)


137
138
139
# File 'lib/sass/tree/node.rb', line 137

def style
  @options[:style]
end

#to_s(*args) ⇒ String?

Computes the CSS corresponding to this static CSS tree.

#to_s shouldn't be overridden directly; instead, override #_to_s. Only static-node subclasses need to implement #to_s.

This may return nil, but it will only do so if #invisible? is true.

Parameters:

  • args (Array)

    Passed on to #_to_s

Returns:

  • (String, nil)

    The resulting CSS

See Also:



151
152
153
154
155
156
# File 'lib/sass/tree/node.rb', line 151

def to_s(*args)
  _to_s(*args)
rescue Sass::SyntaxError => e
  e.modify_backtrace(:filename => filename, :line => line)
  raise e
end

#to_sass(tabs = 0, opts = {}) ⇒ String

Converts a node to Sass code that will generate it.

Parameters:

  • tabs (Fixnum) (defaults to: 0)

    The amount of tabulation to use for the Sass code

  • opts ({Symbol => Object}) (defaults to: {})

    An options hash (see CSS#initialize)

Returns:

  • (String)

    The Sass code corresponding to the node



234
235
236
# File 'lib/sass/tree/node.rb', line 234

def to_sass(tabs = 0, opts = {})
  to_src(tabs, opts, :sass)
end

#to_scss(tabs = 0, opts = {}) ⇒ String

Converts a node to SCSS code that will generate it.

Parameters:

  • tabs (Fixnum) (defaults to: 0)

    The amount of tabulation to use for the SCSS code

  • opts ({Symbol => Object}) (defaults to: {})

    An options hash (see CSS#initialize)

Returns:

  • (String)

    The Sass code corresponding to the node



243
244
245
# File 'lib/sass/tree/node.rb', line 243

def to_scss(tabs = 0, opts = {})
  to_src(tabs, opts, :scss)
end

#to_src(tabs, opts, fmt) ⇒ String (protected)

Converts a node to Sass or SCSS code that will generate it.

This method is called by the default #to_sass and #to_scss methods, so that the same code can be used for both with minor variations.

Parameters:

  • tabs (Fixnum)

    The amount of tabulation to use for the SCSS code

  • opts ({Symbol => Object})

    An options hash (see CSS#initialize)

  • fmt (Symbol)

    :sass or :scss

Returns:

  • (String)

    The Sass or SCSS code corresponding to the node



400
401
402
# File 'lib/sass/tree/node.rb', line 400

def to_src(tabs, opts, fmt)
  Haml::Util.abstract(self)
end