oreorenasass 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +11 -0
- data/CONTRIBUTING +3 -0
- data/MIT-LICENSE +20 -0
- data/README.md +221 -0
- data/Rakefile +370 -0
- data/VERSION +1 -0
- data/VERSION_NAME +1 -0
- data/bin/sass +13 -0
- data/bin/sass-convert +12 -0
- data/bin/scss +13 -0
- data/extra/update_watch.rb +13 -0
- data/init.rb +18 -0
- data/lib/sass/cache_stores/base.rb +88 -0
- data/lib/sass/cache_stores/chain.rb +34 -0
- data/lib/sass/cache_stores/filesystem.rb +60 -0
- data/lib/sass/cache_stores/memory.rb +47 -0
- data/lib/sass/cache_stores/null.rb +25 -0
- data/lib/sass/cache_stores.rb +15 -0
- data/lib/sass/callbacks.rb +67 -0
- data/lib/sass/css.rb +407 -0
- data/lib/sass/engine.rb +1181 -0
- data/lib/sass/environment.rb +191 -0
- data/lib/sass/error.rb +198 -0
- data/lib/sass/exec/base.rb +187 -0
- data/lib/sass/exec/sass_convert.rb +264 -0
- data/lib/sass/exec/sass_scss.rb +424 -0
- data/lib/sass/exec.rb +9 -0
- data/lib/sass/features.rb +47 -0
- data/lib/sass/importers/base.rb +182 -0
- data/lib/sass/importers/filesystem.rb +211 -0
- data/lib/sass/importers.rb +22 -0
- data/lib/sass/logger/base.rb +30 -0
- data/lib/sass/logger/log_level.rb +45 -0
- data/lib/sass/logger.rb +12 -0
- data/lib/sass/media.rb +210 -0
- data/lib/sass/plugin/compiler.rb +565 -0
- data/lib/sass/plugin/configuration.rb +118 -0
- data/lib/sass/plugin/generic.rb +15 -0
- data/lib/sass/plugin/merb.rb +48 -0
- data/lib/sass/plugin/rack.rb +60 -0
- data/lib/sass/plugin/rails.rb +47 -0
- data/lib/sass/plugin/staleness_checker.rb +199 -0
- data/lib/sass/plugin.rb +133 -0
- data/lib/sass/railtie.rb +10 -0
- data/lib/sass/repl.rb +57 -0
- data/lib/sass/root.rb +7 -0
- data/lib/sass/script/css_lexer.rb +33 -0
- data/lib/sass/script/css_parser.rb +34 -0
- data/lib/sass/script/functions.rb +2626 -0
- data/lib/sass/script/lexer.rb +449 -0
- data/lib/sass/script/parser.rb +637 -0
- data/lib/sass/script/tree/funcall.rb +306 -0
- data/lib/sass/script/tree/interpolation.rb +118 -0
- data/lib/sass/script/tree/list_literal.rb +77 -0
- data/lib/sass/script/tree/literal.rb +45 -0
- data/lib/sass/script/tree/map_literal.rb +64 -0
- data/lib/sass/script/tree/node.rb +109 -0
- data/lib/sass/script/tree/operation.rb +103 -0
- data/lib/sass/script/tree/selector.rb +26 -0
- data/lib/sass/script/tree/string_interpolation.rb +104 -0
- data/lib/sass/script/tree/unary_operation.rb +69 -0
- data/lib/sass/script/tree/variable.rb +57 -0
- data/lib/sass/script/tree.rb +16 -0
- data/lib/sass/script/value/arg_list.rb +36 -0
- data/lib/sass/script/value/base.rb +240 -0
- data/lib/sass/script/value/bool.rb +35 -0
- data/lib/sass/script/value/color.rb +680 -0
- data/lib/sass/script/value/helpers.rb +262 -0
- data/lib/sass/script/value/list.rb +113 -0
- data/lib/sass/script/value/map.rb +70 -0
- data/lib/sass/script/value/null.rb +44 -0
- data/lib/sass/script/value/number.rb +530 -0
- data/lib/sass/script/value/string.rb +97 -0
- data/lib/sass/script/value.rb +11 -0
- data/lib/sass/script.rb +66 -0
- data/lib/sass/scss/css_parser.rb +42 -0
- data/lib/sass/scss/parser.rb +1209 -0
- data/lib/sass/scss/rx.rb +141 -0
- data/lib/sass/scss/script_lexer.rb +15 -0
- data/lib/sass/scss/script_parser.rb +25 -0
- data/lib/sass/scss/static_parser.rb +368 -0
- data/lib/sass/scss.rb +16 -0
- data/lib/sass/selector/abstract_sequence.rb +109 -0
- data/lib/sass/selector/comma_sequence.rb +175 -0
- data/lib/sass/selector/pseudo.rb +256 -0
- data/lib/sass/selector/sequence.rb +600 -0
- data/lib/sass/selector/simple.rb +117 -0
- data/lib/sass/selector/simple_sequence.rb +325 -0
- data/lib/sass/selector.rb +326 -0
- data/lib/sass/shared.rb +76 -0
- data/lib/sass/source/map.rb +210 -0
- data/lib/sass/source/position.rb +39 -0
- data/lib/sass/source/range.rb +41 -0
- data/lib/sass/stack.rb +120 -0
- data/lib/sass/supports.rb +227 -0
- data/lib/sass/tree/at_root_node.rb +83 -0
- data/lib/sass/tree/charset_node.rb +22 -0
- data/lib/sass/tree/comment_node.rb +82 -0
- data/lib/sass/tree/content_node.rb +9 -0
- data/lib/sass/tree/css_import_node.rb +60 -0
- data/lib/sass/tree/debug_node.rb +18 -0
- data/lib/sass/tree/directive_node.rb +59 -0
- data/lib/sass/tree/each_node.rb +24 -0
- data/lib/sass/tree/error_node.rb +18 -0
- data/lib/sass/tree/extend_node.rb +43 -0
- data/lib/sass/tree/for_node.rb +36 -0
- data/lib/sass/tree/function_node.rb +39 -0
- data/lib/sass/tree/if_node.rb +52 -0
- data/lib/sass/tree/import_node.rb +74 -0
- data/lib/sass/tree/keyframe_rule_node.rb +15 -0
- data/lib/sass/tree/media_node.rb +48 -0
- data/lib/sass/tree/mixin_def_node.rb +38 -0
- data/lib/sass/tree/mixin_node.rb +52 -0
- data/lib/sass/tree/node.rb +238 -0
- data/lib/sass/tree/prop_node.rb +171 -0
- data/lib/sass/tree/return_node.rb +19 -0
- data/lib/sass/tree/root_node.rb +44 -0
- data/lib/sass/tree/rule_node.rb +145 -0
- data/lib/sass/tree/supports_node.rb +38 -0
- data/lib/sass/tree/trace_node.rb +33 -0
- data/lib/sass/tree/variable_node.rb +36 -0
- data/lib/sass/tree/visitors/base.rb +72 -0
- data/lib/sass/tree/visitors/check_nesting.rb +177 -0
- data/lib/sass/tree/visitors/convert.rb +334 -0
- data/lib/sass/tree/visitors/cssize.rb +369 -0
- data/lib/sass/tree/visitors/deep_copy.rb +107 -0
- data/lib/sass/tree/visitors/extend.rb +68 -0
- data/lib/sass/tree/visitors/perform.rb +539 -0
- data/lib/sass/tree/visitors/set_options.rb +139 -0
- data/lib/sass/tree/visitors/to_css.rb +381 -0
- data/lib/sass/tree/warn_node.rb +18 -0
- data/lib/sass/tree/while_node.rb +18 -0
- data/lib/sass/util/cross_platform_random.rb +19 -0
- data/lib/sass/util/multibyte_string_scanner.rb +157 -0
- data/lib/sass/util/normalized_map.rb +130 -0
- data/lib/sass/util/ordered_hash.rb +192 -0
- data/lib/sass/util/subset_map.rb +110 -0
- data/lib/sass/util/test.rb +9 -0
- data/lib/sass/util.rb +1318 -0
- data/lib/sass/version.rb +124 -0
- data/lib/sass.rb +102 -0
- data/rails/init.rb +1 -0
- data/test/sass/cache_test.rb +131 -0
- data/test/sass/callbacks_test.rb +61 -0
- data/test/sass/compiler_test.rb +232 -0
- data/test/sass/conversion_test.rb +2054 -0
- data/test/sass/css2sass_test.rb +477 -0
- data/test/sass/data/hsl-rgb.txt +319 -0
- data/test/sass/encoding_test.rb +219 -0
- data/test/sass/engine_test.rb +3301 -0
- data/test/sass/exec_test.rb +86 -0
- data/test/sass/extend_test.rb +1661 -0
- data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
- data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
- data/test/sass/functions_test.rb +1926 -0
- data/test/sass/importer_test.rb +412 -0
- data/test/sass/logger_test.rb +58 -0
- data/test/sass/mock_importer.rb +49 -0
- data/test/sass/more_results/more1.css +9 -0
- data/test/sass/more_results/more1_with_line_comments.css +26 -0
- data/test/sass/more_results/more_import.css +29 -0
- data/test/sass/more_templates/_more_partial.sass +2 -0
- data/test/sass/more_templates/more1.sass +23 -0
- data/test/sass/more_templates/more_import.sass +11 -0
- data/test/sass/plugin_test.rb +554 -0
- data/test/sass/results/alt.css +4 -0
- data/test/sass/results/basic.css +9 -0
- data/test/sass/results/cached_import_option.css +3 -0
- data/test/sass/results/compact.css +5 -0
- data/test/sass/results/complex.css +86 -0
- data/test/sass/results/compressed.css +1 -0
- data/test/sass/results/expanded.css +19 -0
- data/test/sass/results/filename_fn.css +3 -0
- data/test/sass/results/if.css +3 -0
- data/test/sass/results/import.css +31 -0
- data/test/sass/results/import_charset.css +5 -0
- data/test/sass/results/import_charset_1_8.css +5 -0
- data/test/sass/results/import_charset_ibm866.css +5 -0
- data/test/sass/results/import_content.css +1 -0
- data/test/sass/results/line_numbers.css +49 -0
- data/test/sass/results/mixins.css +95 -0
- data/test/sass/results/multiline.css +24 -0
- data/test/sass/results/nested.css +22 -0
- data/test/sass/results/options.css +1 -0
- data/test/sass/results/parent_ref.css +13 -0
- data/test/sass/results/script.css +16 -0
- data/test/sass/results/scss_import.css +31 -0
- data/test/sass/results/scss_importee.css +2 -0
- data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
- data/test/sass/results/subdir/subdir.css +3 -0
- data/test/sass/results/units.css +11 -0
- data/test/sass/results/warn.css +0 -0
- data/test/sass/results/warn_imported.css +0 -0
- data/test/sass/script_conversion_test.rb +328 -0
- data/test/sass/script_test.rb +1054 -0
- data/test/sass/scss/css_test.rb +1215 -0
- data/test/sass/scss/rx_test.rb +156 -0
- data/test/sass/scss/scss_test.rb +3900 -0
- data/test/sass/scss/test_helper.rb +37 -0
- data/test/sass/source_map_test.rb +977 -0
- data/test/sass/superselector_test.rb +191 -0
- data/test/sass/templates/_cached_import_option_partial.scss +1 -0
- data/test/sass/templates/_double_import_loop2.sass +1 -0
- data/test/sass/templates/_filename_fn_import.scss +11 -0
- data/test/sass/templates/_imported_charset_ibm866.sass +4 -0
- data/test/sass/templates/_imported_charset_utf8.sass +4 -0
- data/test/sass/templates/_imported_content.sass +3 -0
- data/test/sass/templates/_partial.sass +2 -0
- data/test/sass/templates/_same_name_different_partiality.scss +1 -0
- data/test/sass/templates/alt.sass +16 -0
- data/test/sass/templates/basic.sass +23 -0
- data/test/sass/templates/bork1.sass +2 -0
- data/test/sass/templates/bork2.sass +2 -0
- data/test/sass/templates/bork3.sass +2 -0
- data/test/sass/templates/bork4.sass +2 -0
- data/test/sass/templates/bork5.sass +3 -0
- data/test/sass/templates/cached_import_option.scss +3 -0
- data/test/sass/templates/compact.sass +17 -0
- data/test/sass/templates/complex.sass +305 -0
- data/test/sass/templates/compressed.sass +15 -0
- data/test/sass/templates/double_import_loop1.sass +1 -0
- data/test/sass/templates/expanded.sass +17 -0
- data/test/sass/templates/filename_fn.scss +18 -0
- data/test/sass/templates/if.sass +11 -0
- data/test/sass/templates/import.sass +12 -0
- data/test/sass/templates/import_charset.sass +9 -0
- data/test/sass/templates/import_charset_1_8.sass +6 -0
- data/test/sass/templates/import_charset_ibm866.sass +11 -0
- data/test/sass/templates/import_content.sass +4 -0
- data/test/sass/templates/importee.less +2 -0
- data/test/sass/templates/importee.sass +19 -0
- data/test/sass/templates/line_numbers.sass +13 -0
- data/test/sass/templates/mixin_bork.sass +5 -0
- data/test/sass/templates/mixins.sass +76 -0
- data/test/sass/templates/multiline.sass +20 -0
- data/test/sass/templates/nested.sass +25 -0
- data/test/sass/templates/nested_bork1.sass +2 -0
- data/test/sass/templates/nested_bork2.sass +2 -0
- data/test/sass/templates/nested_bork3.sass +2 -0
- data/test/sass/templates/nested_bork4.sass +2 -0
- data/test/sass/templates/nested_import.sass +2 -0
- data/test/sass/templates/nested_mixin_bork.sass +6 -0
- data/test/sass/templates/options.sass +2 -0
- data/test/sass/templates/parent_ref.sass +25 -0
- data/test/sass/templates/same_name_different_ext.sass +2 -0
- data/test/sass/templates/same_name_different_ext.scss +1 -0
- data/test/sass/templates/same_name_different_partiality.scss +1 -0
- data/test/sass/templates/script.sass +101 -0
- data/test/sass/templates/scss_import.scss +12 -0
- data/test/sass/templates/scss_importee.scss +1 -0
- data/test/sass/templates/single_import_loop.sass +1 -0
- data/test/sass/templates/subdir/import_up1.scss +1 -0
- data/test/sass/templates/subdir/import_up2.scss +1 -0
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
- data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
- data/test/sass/templates/subdir/subdir.sass +6 -0
- data/test/sass/templates/units.sass +11 -0
- data/test/sass/templates/warn.sass +3 -0
- data/test/sass/templates/warn_imported.sass +4 -0
- data/test/sass/test_helper.rb +8 -0
- data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
- data/test/sass/util/normalized_map_test.rb +51 -0
- data/test/sass/util/subset_map_test.rb +91 -0
- data/test/sass/util_test.rb +467 -0
- data/test/sass/value_helpers_test.rb +179 -0
- data/test/test_helper.rb +109 -0
- metadata +386 -0
@@ -0,0 +1,107 @@
|
|
1
|
+
# A visitor for copying the full structure of a Sass tree.
|
2
|
+
class Sass::Tree::Visitors::DeepCopy < Sass::Tree::Visitors::Base
|
3
|
+
protected
|
4
|
+
|
5
|
+
def visit(node)
|
6
|
+
super(node.dup)
|
7
|
+
end
|
8
|
+
|
9
|
+
def visit_children(parent)
|
10
|
+
parent.children = parent.children.map {|c| visit(c)}
|
11
|
+
parent
|
12
|
+
end
|
13
|
+
|
14
|
+
def visit_debug(node)
|
15
|
+
node.expr = node.expr.deep_copy
|
16
|
+
yield
|
17
|
+
end
|
18
|
+
|
19
|
+
def visit_error(node)
|
20
|
+
node.expr = node.expr.deep_copy
|
21
|
+
yield
|
22
|
+
end
|
23
|
+
|
24
|
+
def visit_each(node)
|
25
|
+
node.list = node.list.deep_copy
|
26
|
+
yield
|
27
|
+
end
|
28
|
+
|
29
|
+
def visit_extend(node)
|
30
|
+
node.selector = node.selector.map {|c| c.is_a?(Sass::Script::Tree::Node) ? c.deep_copy : c}
|
31
|
+
yield
|
32
|
+
end
|
33
|
+
|
34
|
+
def visit_for(node)
|
35
|
+
node.from = node.from.deep_copy
|
36
|
+
node.to = node.to.deep_copy
|
37
|
+
yield
|
38
|
+
end
|
39
|
+
|
40
|
+
def visit_function(node)
|
41
|
+
node.args = node.args.map {|k, v| [k.deep_copy, v && v.deep_copy]}
|
42
|
+
yield
|
43
|
+
end
|
44
|
+
|
45
|
+
def visit_if(node)
|
46
|
+
node.expr = node.expr.deep_copy if node.expr
|
47
|
+
node.else = visit(node.else) if node.else
|
48
|
+
yield
|
49
|
+
end
|
50
|
+
|
51
|
+
def visit_mixindef(node)
|
52
|
+
node.args = node.args.map {|k, v| [k.deep_copy, v && v.deep_copy]}
|
53
|
+
yield
|
54
|
+
end
|
55
|
+
|
56
|
+
def visit_mixin(node)
|
57
|
+
node.args = node.args.map {|a| a.deep_copy}
|
58
|
+
node.keywords = Hash[node.keywords.map {|k, v| [k, v.deep_copy]}]
|
59
|
+
yield
|
60
|
+
end
|
61
|
+
|
62
|
+
def visit_prop(node)
|
63
|
+
node.name = node.name.map {|c| c.is_a?(Sass::Script::Tree::Node) ? c.deep_copy : c}
|
64
|
+
node.value = node.value.deep_copy
|
65
|
+
yield
|
66
|
+
end
|
67
|
+
|
68
|
+
def visit_return(node)
|
69
|
+
node.expr = node.expr.deep_copy
|
70
|
+
yield
|
71
|
+
end
|
72
|
+
|
73
|
+
def visit_rule(node)
|
74
|
+
node.rule = node.rule.map {|c| c.is_a?(Sass::Script::Tree::Node) ? c.deep_copy : c}
|
75
|
+
yield
|
76
|
+
end
|
77
|
+
|
78
|
+
def visit_variable(node)
|
79
|
+
node.expr = node.expr.deep_copy
|
80
|
+
yield
|
81
|
+
end
|
82
|
+
|
83
|
+
def visit_warn(node)
|
84
|
+
node.expr = node.expr.deep_copy
|
85
|
+
yield
|
86
|
+
end
|
87
|
+
|
88
|
+
def visit_while(node)
|
89
|
+
node.expr = node.expr.deep_copy
|
90
|
+
yield
|
91
|
+
end
|
92
|
+
|
93
|
+
def visit_directive(node)
|
94
|
+
node.value = node.value.map {|c| c.is_a?(Sass::Script::Tree::Node) ? c.deep_copy : c}
|
95
|
+
yield
|
96
|
+
end
|
97
|
+
|
98
|
+
def visit_media(node)
|
99
|
+
node.query = node.query.map {|c| c.is_a?(Sass::Script::Tree::Node) ? c.deep_copy : c}
|
100
|
+
yield
|
101
|
+
end
|
102
|
+
|
103
|
+
def visit_supports(node)
|
104
|
+
node.condition = node.condition.deep_copy
|
105
|
+
yield
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# A visitor for performing selector inheritance on a static CSS tree.
|
2
|
+
#
|
3
|
+
# Destructively modifies the tree.
|
4
|
+
class Sass::Tree::Visitors::Extend < Sass::Tree::Visitors::Base
|
5
|
+
# Performs the given extensions on the static CSS tree based in `root`, then
|
6
|
+
# validates that all extends matched some selector.
|
7
|
+
#
|
8
|
+
# @param root [Tree::Node] The root node of the tree to visit.
|
9
|
+
# @param extends [Sass::Util::SubsetMap{Selector::Simple =>
|
10
|
+
# Sass::Tree::Visitors::Cssize::Extend}]
|
11
|
+
# The extensions to perform on this tree.
|
12
|
+
# @return [Object] The return value of \{#visit} for the root node.
|
13
|
+
def self.visit(root, extends)
|
14
|
+
return if extends.empty?
|
15
|
+
new(extends).send(:visit, root)
|
16
|
+
check_extends_fired! extends
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def initialize(extends)
|
22
|
+
@parent_directives = []
|
23
|
+
@extends = extends
|
24
|
+
end
|
25
|
+
|
26
|
+
# If an exception is raised, this adds proper metadata to the backtrace.
|
27
|
+
def visit(node)
|
28
|
+
super(node)
|
29
|
+
rescue Sass::SyntaxError => e
|
30
|
+
e.modify_backtrace(:filename => node.filename, :line => node.line)
|
31
|
+
raise e
|
32
|
+
end
|
33
|
+
|
34
|
+
# Keeps track of the current parent directives.
|
35
|
+
def visit_children(parent)
|
36
|
+
@parent_directives.push parent if parent.is_a?(Sass::Tree::DirectiveNode)
|
37
|
+
super
|
38
|
+
ensure
|
39
|
+
@parent_directives.pop if parent.is_a?(Sass::Tree::DirectiveNode)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Applies the extend to a single rule's selector.
|
43
|
+
def visit_rule(node)
|
44
|
+
node.resolved_rules = node.resolved_rules.do_extend(@extends, @parent_directives)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def self.check_extends_fired!(extends)
|
50
|
+
extends.each_value do |ex|
|
51
|
+
next if ex.result == :succeeded || ex.node.optional?
|
52
|
+
message = "\"#{ex.extender}\" failed to @extend \"#{ex.target.join}\"."
|
53
|
+
reason =
|
54
|
+
if ex.result == :not_found
|
55
|
+
"The selector \"#{ex.target.join}\" was not found."
|
56
|
+
else
|
57
|
+
"No selectors matching \"#{ex.target.join}\" could be unified with \"#{ex.extender}\"."
|
58
|
+
end
|
59
|
+
|
60
|
+
# TODO(nweiz): this should use the Sass stack trace of the extend node.
|
61
|
+
raise Sass::SyntaxError.new(<<MESSAGE, :filename => ex.node.filename, :line => ex.node.line)
|
62
|
+
#{message}
|
63
|
+
#{reason}
|
64
|
+
Use "@extend #{ex.target.join} !optional" if the extend should be able to fail.
|
65
|
+
MESSAGE
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,539 @@
|
|
1
|
+
# A visitor for converting a dynamic Sass tree into a static Sass tree.
|
2
|
+
class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
|
3
|
+
class << self
|
4
|
+
# @param root [Tree::Node] The root node of the tree to visit.
|
5
|
+
# @param environment [Sass::Environment] The lexical environment.
|
6
|
+
# @return [Tree::Node] The resulting tree of static nodes.
|
7
|
+
def visit(root, environment = nil)
|
8
|
+
new(environment).send(:visit, root)
|
9
|
+
end
|
10
|
+
|
11
|
+
# @api private
|
12
|
+
# @comment
|
13
|
+
# rubocop:disable MethodLength
|
14
|
+
def perform_arguments(callable, args, splat)
|
15
|
+
desc = "#{callable.type.capitalize} #{callable.name}"
|
16
|
+
downcase_desc = "#{callable.type} #{callable.name}"
|
17
|
+
|
18
|
+
# All keywords are contained in splat.keywords for consistency,
|
19
|
+
# even if there were no splats passed in.
|
20
|
+
old_keywords_accessed = splat.keywords_accessed
|
21
|
+
keywords = splat.keywords
|
22
|
+
splat.keywords_accessed = old_keywords_accessed
|
23
|
+
|
24
|
+
begin
|
25
|
+
unless keywords.empty?
|
26
|
+
unknown_args = Sass::Util.array_minus(keywords.keys,
|
27
|
+
callable.args.map {|var| var.first.underscored_name})
|
28
|
+
if callable.splat && unknown_args.include?(callable.splat.underscored_name)
|
29
|
+
raise Sass::SyntaxError.new("Argument $#{callable.splat.name} of #{downcase_desc} " +
|
30
|
+
"cannot be used as a named argument.")
|
31
|
+
elsif unknown_args.any?
|
32
|
+
description = unknown_args.length > 1 ? 'the following arguments:' : 'an argument named'
|
33
|
+
raise Sass::SyntaxError.new("#{desc} doesn't have #{description} " +
|
34
|
+
"#{unknown_args.map {|name| "$#{name}"}.join ', '}.")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
rescue Sass::SyntaxError => keyword_exception
|
38
|
+
end
|
39
|
+
|
40
|
+
# If there's no splat, raise the keyword exception immediately. The actual
|
41
|
+
# raising happens in the ensure clause at the end of this function.
|
42
|
+
return if keyword_exception && !callable.splat
|
43
|
+
|
44
|
+
if args.size > callable.args.size && !callable.splat
|
45
|
+
takes = callable.args.size
|
46
|
+
passed = args.size
|
47
|
+
raise Sass::SyntaxError.new(
|
48
|
+
"#{desc} takes #{takes} argument#{'s' unless takes == 1} " +
|
49
|
+
"but #{passed} #{passed == 1 ? 'was' : 'were'} passed.")
|
50
|
+
end
|
51
|
+
|
52
|
+
splat_sep = :comma
|
53
|
+
if splat
|
54
|
+
args += splat.to_a
|
55
|
+
splat_sep = splat.separator
|
56
|
+
end
|
57
|
+
|
58
|
+
env = Sass::Environment.new(callable.environment)
|
59
|
+
callable.args.zip(args[0...callable.args.length]) do |(var, default), value|
|
60
|
+
if value && keywords.has_key?(var.name)
|
61
|
+
raise Sass::SyntaxError.new("#{desc} was passed argument $#{var.name} " +
|
62
|
+
"both by position and by name.")
|
63
|
+
end
|
64
|
+
|
65
|
+
value ||= keywords.delete(var.name)
|
66
|
+
value ||= default && default.perform(env)
|
67
|
+
raise Sass::SyntaxError.new("#{desc} is missing argument #{var.inspect}.") unless value
|
68
|
+
env.set_local_var(var.name, value)
|
69
|
+
end
|
70
|
+
|
71
|
+
if callable.splat
|
72
|
+
rest = args[callable.args.length..-1] || []
|
73
|
+
arg_list = Sass::Script::Value::ArgList.new(rest, keywords, splat_sep)
|
74
|
+
arg_list.options = env.options
|
75
|
+
env.set_local_var(callable.splat.name, arg_list)
|
76
|
+
end
|
77
|
+
|
78
|
+
yield env
|
79
|
+
rescue StandardError => e
|
80
|
+
ensure
|
81
|
+
# If there's a keyword exception, we don't want to throw it immediately,
|
82
|
+
# because the invalid keywords may be part of a glob argument that should be
|
83
|
+
# passed on to another function. So we only raise it if we reach the end of
|
84
|
+
# this function *and* the keywords attached to the argument list glob object
|
85
|
+
# haven't been accessed.
|
86
|
+
#
|
87
|
+
# The keyword exception takes precedence over any Sass errors, but not over
|
88
|
+
# non-Sass exceptions.
|
89
|
+
if keyword_exception &&
|
90
|
+
!(arg_list && arg_list.keywords_accessed) &&
|
91
|
+
(e.nil? || e.is_a?(Sass::SyntaxError))
|
92
|
+
raise keyword_exception
|
93
|
+
elsif e
|
94
|
+
raise e
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# @api private
|
99
|
+
# @return [Sass::Script::Value::ArgList]
|
100
|
+
def perform_splat(splat, performed_keywords, kwarg_splat, environment)
|
101
|
+
args, kwargs, separator = [], nil, :comma
|
102
|
+
|
103
|
+
if splat
|
104
|
+
splat = splat.perform(environment)
|
105
|
+
separator = splat.separator || separator
|
106
|
+
if splat.is_a?(Sass::Script::Value::ArgList)
|
107
|
+
args = splat.to_a
|
108
|
+
kwargs = splat.keywords
|
109
|
+
elsif splat.is_a?(Sass::Script::Value::Map)
|
110
|
+
kwargs = arg_hash(splat)
|
111
|
+
else
|
112
|
+
args = splat.to_a
|
113
|
+
end
|
114
|
+
end
|
115
|
+
kwargs ||= Sass::Util::NormalizedMap.new
|
116
|
+
kwargs.update(performed_keywords)
|
117
|
+
|
118
|
+
if kwarg_splat
|
119
|
+
kwarg_splat = kwarg_splat.perform(environment)
|
120
|
+
unless kwarg_splat.is_a?(Sass::Script::Value::Map)
|
121
|
+
raise Sass::SyntaxError.new("Variable keyword arguments must be a map " +
|
122
|
+
"(was #{kwarg_splat.inspect}).")
|
123
|
+
end
|
124
|
+
kwargs.update(arg_hash(kwarg_splat))
|
125
|
+
end
|
126
|
+
|
127
|
+
Sass::Script::Value::ArgList.new(args, kwargs, separator)
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def arg_hash(map)
|
133
|
+
Sass::Util.map_keys(map.to_h) do |key|
|
134
|
+
next key.value if key.is_a?(Sass::Script::Value::String)
|
135
|
+
raise Sass::SyntaxError.new("Variable keyword argument map must have string keys.\n" +
|
136
|
+
"#{key.inspect} is not a string in #{map.inspect}.")
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
# @comment
|
141
|
+
# rubocop:enable MethodLength
|
142
|
+
|
143
|
+
protected
|
144
|
+
|
145
|
+
def initialize(env)
|
146
|
+
@environment = env
|
147
|
+
end
|
148
|
+
|
149
|
+
# If an exception is raised, this adds proper metadata to the backtrace.
|
150
|
+
def visit(node)
|
151
|
+
return super(node.dup) unless @environment
|
152
|
+
@environment.stack.with_base(node.filename, node.line) {super(node.dup)}
|
153
|
+
rescue Sass::SyntaxError => e
|
154
|
+
e.modify_backtrace(:filename => node.filename, :line => node.line)
|
155
|
+
raise e
|
156
|
+
end
|
157
|
+
|
158
|
+
# Keeps track of the current environment.
|
159
|
+
def visit_children(parent)
|
160
|
+
with_environment Sass::Environment.new(@environment, parent.options) do
|
161
|
+
parent.children = super.flatten
|
162
|
+
parent
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Runs a block of code with the current environment replaced with the given one.
|
167
|
+
#
|
168
|
+
# @param env [Sass::Environment] The new environment for the duration of the block.
|
169
|
+
# @yield A block in which the environment is set to `env`.
|
170
|
+
# @return [Object] The return value of the block.
|
171
|
+
def with_environment(env)
|
172
|
+
old_env, @environment = @environment, env
|
173
|
+
yield
|
174
|
+
ensure
|
175
|
+
@environment = old_env
|
176
|
+
end
|
177
|
+
|
178
|
+
# Sets the options on the environment if this is the top-level root.
|
179
|
+
def visit_root(node)
|
180
|
+
yield
|
181
|
+
rescue Sass::SyntaxError => e
|
182
|
+
e.sass_template ||= node.template
|
183
|
+
raise e
|
184
|
+
end
|
185
|
+
|
186
|
+
# Removes this node from the tree if it's a silent comment.
|
187
|
+
def visit_comment(node)
|
188
|
+
return [] if node.invisible?
|
189
|
+
node.resolved_value = run_interp_no_strip(node.value)
|
190
|
+
node.resolved_value.gsub!(/\\([\\#])/, '\1')
|
191
|
+
node
|
192
|
+
end
|
193
|
+
|
194
|
+
# Prints the expression to STDERR.
|
195
|
+
def visit_debug(node)
|
196
|
+
res = node.expr.perform(@environment)
|
197
|
+
if res.is_a?(Sass::Script::Value::String)
|
198
|
+
res = res.value
|
199
|
+
else
|
200
|
+
res = res.to_sass
|
201
|
+
end
|
202
|
+
if node.filename
|
203
|
+
Sass::Util.sass_warn "#{node.filename}:#{node.line} DEBUG: #{res}"
|
204
|
+
else
|
205
|
+
Sass::Util.sass_warn "Line #{node.line} DEBUG: #{res}"
|
206
|
+
end
|
207
|
+
[]
|
208
|
+
end
|
209
|
+
|
210
|
+
# Throws the expression as an error.
|
211
|
+
def visit_error(node)
|
212
|
+
res = node.expr.perform(@environment)
|
213
|
+
if res.is_a?(Sass::Script::Value::String)
|
214
|
+
res = res.value
|
215
|
+
else
|
216
|
+
res = res.to_sass
|
217
|
+
end
|
218
|
+
raise Sass::SyntaxError.new(res)
|
219
|
+
end
|
220
|
+
|
221
|
+
# Runs the child nodes once for each value in the list.
|
222
|
+
def visit_each(node)
|
223
|
+
list = node.list.perform(@environment)
|
224
|
+
|
225
|
+
with_environment Sass::Environment.new(@environment) do
|
226
|
+
list.to_a.map do |value|
|
227
|
+
if node.vars.length == 1
|
228
|
+
@environment.set_local_var(node.vars.first, value)
|
229
|
+
else
|
230
|
+
node.vars.zip(value.to_a) do |(var, sub_value)|
|
231
|
+
@environment.set_local_var(var, sub_value || Sass::Script::Value::Null.new)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
node.children.map {|c| visit(c)}
|
235
|
+
end.flatten
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
# Runs SassScript interpolation in the selector,
|
240
|
+
# and then parses the result into a {Sass::Selector::CommaSequence}.
|
241
|
+
def visit_extend(node)
|
242
|
+
parser = Sass::SCSS::StaticParser.new(run_interp(node.selector),
|
243
|
+
node.filename, node.options[:importer], node.line)
|
244
|
+
node.resolved_selector = parser.parse_selector
|
245
|
+
node
|
246
|
+
end
|
247
|
+
|
248
|
+
# Runs the child nodes once for each time through the loop, varying the variable each time.
|
249
|
+
def visit_for(node)
|
250
|
+
from = node.from.perform(@environment)
|
251
|
+
to = node.to.perform(@environment)
|
252
|
+
from.assert_int!
|
253
|
+
to.assert_int!
|
254
|
+
|
255
|
+
to = to.coerce(from.numerator_units, from.denominator_units)
|
256
|
+
direction = from.to_i > to.to_i ? -1 : 1
|
257
|
+
range = Range.new(direction * from.to_i, direction * to.to_i, node.exclusive)
|
258
|
+
|
259
|
+
with_environment Sass::Environment.new(@environment) do
|
260
|
+
range.map do |i|
|
261
|
+
@environment.set_local_var(node.var,
|
262
|
+
Sass::Script::Value::Number.new(direction * i,
|
263
|
+
from.numerator_units, from.denominator_units))
|
264
|
+
node.children.map {|c| visit(c)}
|
265
|
+
end.flatten
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
# Loads the function into the environment.
|
270
|
+
def visit_function(node)
|
271
|
+
env = Sass::Environment.new(@environment, node.options)
|
272
|
+
@environment.set_local_function(node.name,
|
273
|
+
Sass::Callable.new(node.name, node.args, node.splat, env,
|
274
|
+
node.children, !:has_content, "function"))
|
275
|
+
[]
|
276
|
+
end
|
277
|
+
|
278
|
+
# Runs the child nodes if the conditional expression is true;
|
279
|
+
# otherwise, tries the else nodes.
|
280
|
+
def visit_if(node)
|
281
|
+
if node.expr.nil? || node.expr.perform(@environment).to_bool
|
282
|
+
yield
|
283
|
+
node.children
|
284
|
+
elsif node.else
|
285
|
+
visit(node.else)
|
286
|
+
else
|
287
|
+
[]
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
# Returns a static DirectiveNode if this is importing a CSS file,
|
292
|
+
# or parses and includes the imported Sass file.
|
293
|
+
def visit_import(node)
|
294
|
+
if (path = node.css_import?)
|
295
|
+
resolved_node = Sass::Tree::CssImportNode.resolved("url(#{path})")
|
296
|
+
resolved_node.source_range = node.source_range
|
297
|
+
return resolved_node
|
298
|
+
end
|
299
|
+
file = node.imported_file
|
300
|
+
if @environment.stack.frames.any? {|f| f.is_import? && f.filename == file.options[:filename]}
|
301
|
+
handle_import_loop!(node)
|
302
|
+
end
|
303
|
+
|
304
|
+
begin
|
305
|
+
@environment.stack.with_import(node.filename, node.line) do
|
306
|
+
root = file.to_tree
|
307
|
+
Sass::Tree::Visitors::CheckNesting.visit(root)
|
308
|
+
node.children = root.children.map {|c| visit(c)}.flatten
|
309
|
+
node
|
310
|
+
end
|
311
|
+
rescue Sass::SyntaxError => e
|
312
|
+
e.modify_backtrace(:filename => node.imported_file.options[:filename])
|
313
|
+
e.add_backtrace(:filename => node.filename, :line => node.line)
|
314
|
+
raise e
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
# Loads a mixin into the environment.
|
319
|
+
def visit_mixindef(node)
|
320
|
+
env = Sass::Environment.new(@environment, node.options)
|
321
|
+
@environment.set_local_mixin(node.name,
|
322
|
+
Sass::Callable.new(node.name, node.args, node.splat, env,
|
323
|
+
node.children, node.has_content, "mixin"))
|
324
|
+
[]
|
325
|
+
end
|
326
|
+
|
327
|
+
# Runs a mixin.
|
328
|
+
def visit_mixin(node)
|
329
|
+
@environment.stack.with_mixin(node.filename, node.line, node.name) do
|
330
|
+
mixin = @environment.mixin(node.name)
|
331
|
+
raise Sass::SyntaxError.new("Undefined mixin '#{node.name}'.") unless mixin
|
332
|
+
|
333
|
+
if node.children.any? && !mixin.has_content
|
334
|
+
raise Sass::SyntaxError.new(%Q{Mixin "#{node.name}" does not accept a content block.})
|
335
|
+
end
|
336
|
+
|
337
|
+
args = node.args.map {|a| a.perform(@environment)}
|
338
|
+
keywords = Sass::Util.map_vals(node.keywords) {|v| v.perform(@environment)}
|
339
|
+
splat = self.class.perform_splat(node.splat, keywords, node.kwarg_splat, @environment)
|
340
|
+
|
341
|
+
self.class.perform_arguments(mixin, args, splat) do |env|
|
342
|
+
env.caller = Sass::Environment.new(@environment)
|
343
|
+
env.content = [node.children, @environment] if node.has_children
|
344
|
+
|
345
|
+
trace_node = Sass::Tree::TraceNode.from_node(node.name, node)
|
346
|
+
with_environment(env) {trace_node.children = mixin.tree.map {|c| visit(c)}.flatten}
|
347
|
+
trace_node
|
348
|
+
end
|
349
|
+
end
|
350
|
+
rescue Sass::SyntaxError => e
|
351
|
+
e.modify_backtrace(:mixin => node.name, :line => node.line)
|
352
|
+
e.add_backtrace(:line => node.line)
|
353
|
+
raise e
|
354
|
+
end
|
355
|
+
|
356
|
+
def visit_content(node)
|
357
|
+
content, content_env = @environment.content
|
358
|
+
return [] unless content
|
359
|
+
@environment.stack.with_mixin(node.filename, node.line, '@content') do
|
360
|
+
trace_node = Sass::Tree::TraceNode.from_node('@content', node)
|
361
|
+
content_env = Sass::Environment.new(content_env)
|
362
|
+
content_env.caller = Sass::Environment.new(@environment)
|
363
|
+
with_environment(content_env) do
|
364
|
+
trace_node.children = content.map {|c| visit(c.dup)}.flatten
|
365
|
+
end
|
366
|
+
trace_node
|
367
|
+
end
|
368
|
+
rescue Sass::SyntaxError => e
|
369
|
+
e.modify_backtrace(:mixin => '@content', :line => node.line)
|
370
|
+
e.add_backtrace(:line => node.line)
|
371
|
+
raise e
|
372
|
+
end
|
373
|
+
|
374
|
+
# Runs any SassScript that may be embedded in a property.
|
375
|
+
def visit_prop(node)
|
376
|
+
node.resolved_name = run_interp(node.name)
|
377
|
+
val = node.value.perform(@environment)
|
378
|
+
node.resolved_value = val.to_s
|
379
|
+
node.value_source_range = val.source_range if val.source_range
|
380
|
+
yield
|
381
|
+
end
|
382
|
+
|
383
|
+
# Returns the value of the expression.
|
384
|
+
def visit_return(node)
|
385
|
+
throw :_sass_return, node.expr.perform(@environment)
|
386
|
+
end
|
387
|
+
|
388
|
+
# Runs SassScript interpolation in the selector,
|
389
|
+
# and then parses the result into a {Sass::Selector::CommaSequence}.
|
390
|
+
def visit_rule(node)
|
391
|
+
old_at_root_without_rule = @at_root_without_rule
|
392
|
+
parser = Sass::SCSS::StaticParser.new(run_interp(node.rule),
|
393
|
+
node.filename, node.options[:importer], node.line)
|
394
|
+
if @in_keyframes
|
395
|
+
keyframe_rule_node = Sass::Tree::KeyframeRuleNode.new(parser.parse_keyframes_selector)
|
396
|
+
keyframe_rule_node.options = node.options
|
397
|
+
keyframe_rule_node.line = node.line
|
398
|
+
keyframe_rule_node.filename = node.filename
|
399
|
+
keyframe_rule_node.source_range = node.source_range
|
400
|
+
with_environment Sass::Environment.new(@environment, node.options) do
|
401
|
+
keyframe_rule_node.children = node.children.map {|c| visit(c)}.flatten
|
402
|
+
end
|
403
|
+
keyframe_rule_node
|
404
|
+
else
|
405
|
+
@at_root_without_rule = false
|
406
|
+
node.parsed_rules ||= parser.parse_selector
|
407
|
+
node.resolved_rules = node.parsed_rules.resolve_parent_refs(
|
408
|
+
@environment.selector, !old_at_root_without_rule)
|
409
|
+
node.stack_trace = @environment.stack.to_s if node.options[:trace_selectors]
|
410
|
+
with_environment Sass::Environment.new(@environment, node.options) do
|
411
|
+
@environment.selector = node.resolved_rules
|
412
|
+
node.children = node.children.map {|c| visit(c)}.flatten
|
413
|
+
end
|
414
|
+
node
|
415
|
+
end
|
416
|
+
ensure
|
417
|
+
@at_root_without_rule = old_at_root_without_rule
|
418
|
+
end
|
419
|
+
|
420
|
+
# Sets a variable that indicates that the first level of rule nodes
|
421
|
+
# shouldn't include the parent selector by default.
|
422
|
+
def visit_atroot(node)
|
423
|
+
if node.query
|
424
|
+
parser = Sass::SCSS::StaticParser.new(run_interp(node.query),
|
425
|
+
node.filename, node.options[:importer], node.line)
|
426
|
+
node.resolved_type, node.resolved_value = parser.parse_static_at_root_query
|
427
|
+
else
|
428
|
+
node.resolved_type, node.resolved_value = :without, ['rule']
|
429
|
+
end
|
430
|
+
|
431
|
+
old_at_root_without_rule = @at_root_without_rule
|
432
|
+
old_in_keyframes = @in_keyframes
|
433
|
+
@at_root_without_rule = true if node.exclude?('rule')
|
434
|
+
@in_keyframes = false if node.exclude?('keyframes')
|
435
|
+
yield
|
436
|
+
ensure
|
437
|
+
@in_keyframes = old_in_keyframes
|
438
|
+
@at_root_without_rule = old_at_root_without_rule
|
439
|
+
end
|
440
|
+
|
441
|
+
# Loads the new variable value into the environment.
|
442
|
+
def visit_variable(node)
|
443
|
+
env = @environment
|
444
|
+
env = env.global_env if node.global
|
445
|
+
if node.guarded
|
446
|
+
var = env.var(node.name)
|
447
|
+
return [] if var && !var.null?
|
448
|
+
end
|
449
|
+
|
450
|
+
val = node.expr.perform(@environment)
|
451
|
+
if node.expr.source_range
|
452
|
+
val.source_range = node.expr.source_range
|
453
|
+
else
|
454
|
+
val.source_range = node.source_range
|
455
|
+
end
|
456
|
+
env.set_var(node.name, val)
|
457
|
+
[]
|
458
|
+
end
|
459
|
+
|
460
|
+
# Prints the expression to STDERR with a stylesheet trace.
|
461
|
+
def visit_warn(node)
|
462
|
+
res = node.expr.perform(@environment)
|
463
|
+
res = res.value if res.is_a?(Sass::Script::Value::String)
|
464
|
+
msg = "WARNING: #{res}\n "
|
465
|
+
msg << @environment.stack.to_s.gsub("\n", "\n ") << "\n"
|
466
|
+
Sass::Util.sass_warn msg
|
467
|
+
[]
|
468
|
+
end
|
469
|
+
|
470
|
+
# Runs the child nodes until the continuation expression becomes false.
|
471
|
+
def visit_while(node)
|
472
|
+
children = []
|
473
|
+
with_environment Sass::Environment.new(@environment) do
|
474
|
+
children += node.children.map {|c| visit(c)} while node.expr.perform(@environment).to_bool
|
475
|
+
end
|
476
|
+
children.flatten
|
477
|
+
end
|
478
|
+
|
479
|
+
def visit_directive(node)
|
480
|
+
node.resolved_value = run_interp(node.value)
|
481
|
+
old_in_keyframes, @in_keyframes = @in_keyframes, node.normalized_name == "@keyframes"
|
482
|
+
with_environment Sass::Environment.new(@environment) do
|
483
|
+
node.children = node.children.map {|c| visit(c)}.flatten
|
484
|
+
node
|
485
|
+
end
|
486
|
+
ensure
|
487
|
+
@in_keyframes = old_in_keyframes
|
488
|
+
end
|
489
|
+
|
490
|
+
def visit_media(node)
|
491
|
+
parser = Sass::SCSS::StaticParser.new(run_interp(node.query),
|
492
|
+
node.filename, node.options[:importer], node.line)
|
493
|
+
node.resolved_query ||= parser.parse_media_query_list
|
494
|
+
yield
|
495
|
+
end
|
496
|
+
|
497
|
+
def visit_supports(node)
|
498
|
+
node.condition = node.condition.deep_copy
|
499
|
+
node.condition.perform(@environment)
|
500
|
+
yield
|
501
|
+
end
|
502
|
+
|
503
|
+
def visit_cssimport(node)
|
504
|
+
node.resolved_uri = run_interp([node.uri])
|
505
|
+
if node.query && !node.query.empty?
|
506
|
+
parser = Sass::SCSS::StaticParser.new(run_interp(node.query),
|
507
|
+
node.filename, node.options[:importer], node.line)
|
508
|
+
node.resolved_query ||= parser.parse_media_query_list
|
509
|
+
end
|
510
|
+
yield
|
511
|
+
end
|
512
|
+
|
513
|
+
private
|
514
|
+
|
515
|
+
def run_interp_no_strip(text)
|
516
|
+
text.map do |r|
|
517
|
+
next r if r.is_a?(String)
|
518
|
+
r.perform(@environment).to_s(:quote => :none)
|
519
|
+
end.join
|
520
|
+
end
|
521
|
+
|
522
|
+
def run_interp(text)
|
523
|
+
run_interp_no_strip(text).strip
|
524
|
+
end
|
525
|
+
|
526
|
+
def handle_import_loop!(node)
|
527
|
+
msg = "An @import loop has been found:"
|
528
|
+
files = @environment.stack.frames.select {|f| f.is_import?}.map {|f| f.filename}.compact
|
529
|
+
if node.filename == node.imported_file.options[:filename]
|
530
|
+
raise Sass::SyntaxError.new("#{msg} #{node.filename} imports itself")
|
531
|
+
end
|
532
|
+
|
533
|
+
files << node.filename << node.imported_file.options[:filename]
|
534
|
+
msg << "\n" << Sass::Util.enum_cons(files, 2).map do |m1, m2|
|
535
|
+
" #{m1} imports #{m2}"
|
536
|
+
end.join("\n")
|
537
|
+
raise Sass::SyntaxError.new(msg)
|
538
|
+
end
|
539
|
+
end
|