File: extend.rb

package info (click to toggle)
ruby-sass 3.7.4-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,396 kB
  • sloc: ruby: 32,443; sh: 26; makefile: 25
file content (64 lines) | stat: -rw-r--r-- 2,103 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# A visitor for performing selector inheritance on a static CSS tree.
#
# Destructively modifies the tree.
class Sass::Tree::Visitors::Extend < Sass::Tree::Visitors::Base
  # Performs the given extensions on the static CSS tree based in `root`, then
  # validates that all extends matched some selector.
  #
  # @param root [Tree::Node] The root node of the tree to visit.
  # @param extends [Sass::Util::SubsetMap{Selector::Simple =>
  #                                       Sass::Tree::Visitors::Cssize::Extend}]
  #   The extensions to perform on this tree.
  # @return [Object] The return value of \{#visit} for the root node.
  def self.visit(root, extends)
    return if extends.empty?
    new(extends).send(:visit, root)
    check_extends_fired! extends
  end

  protected

  def initialize(extends)
    @parent_directives = []
    @extends = extends
  end

  # 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

  # Keeps track of the current parent directives.
  def visit_children(parent)
    @parent_directives.push parent if parent.is_a?(Sass::Tree::DirectiveNode)
    super
  ensure
    @parent_directives.pop if parent.is_a?(Sass::Tree::DirectiveNode)
  end

  # Applies the extend to a single rule's selector.
  def visit_rule(node)
    node.resolved_rules = node.resolved_rules.do_extend(@extends, @parent_directives)
  end

  class << self
    private

    def check_extends_fired!(extends)
      extends.each_value do |ex|
        next if ex.success || ex.node.optional?
        message = "\"#{ex.extender}\" failed to @extend \"#{ex.target.join}\"."

        # TODO(nweiz): this should use the Sass stack trace of the extend node.
        raise Sass::SyntaxError.new(<<MESSAGE, :filename => ex.node.filename, :line => ex.node.line)
#{message}
The selector "#{ex.target.join}" was not found.
Use "@extend #{ex.target.join} !optional" if the extend should be able to fail.
MESSAGE
      end
    end
  end
end