sass 3.1.0 → 3.3.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/CONTRIBUTING +1 -1
- data/MIT-LICENSE +2 -2
- data/README.md +29 -17
- data/Rakefile +43 -9
- data/VERSION +1 -1
- data/VERSION_DATE +1 -0
- data/VERSION_NAME +1 -1
- data/bin/sass +6 -1
- data/bin/sass-convert +6 -1
- data/bin/scss +6 -1
- data/ext/mkrf_conf.rb +27 -0
- data/lib/sass/cache_stores/base.rb +7 -3
- data/lib/sass/cache_stores/chain.rb +3 -2
- data/lib/sass/cache_stores/filesystem.rb +5 -7
- data/lib/sass/cache_stores/memory.rb +1 -1
- data/lib/sass/cache_stores/null.rb +2 -2
- data/lib/sass/callbacks.rb +2 -1
- data/lib/sass/css.rb +168 -53
- data/lib/sass/engine.rb +502 -174
- data/lib/sass/environment.rb +151 -111
- data/lib/sass/error.rb +7 -7
- data/lib/sass/exec.rb +176 -60
- data/lib/sass/features.rb +40 -0
- data/lib/sass/importers/base.rb +46 -7
- data/lib/sass/importers/deprecated_path.rb +51 -0
- data/lib/sass/importers/filesystem.rb +113 -30
- data/lib/sass/importers.rb +1 -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 +213 -0
- data/lib/sass/plugin/compiler.rb +194 -104
- data/lib/sass/plugin/configuration.rb +18 -25
- data/lib/sass/plugin/merb.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +37 -11
- data/lib/sass/plugin.rb +10 -13
- data/lib/sass/railtie.rb +2 -1
- data/lib/sass/repl.rb +5 -6
- data/lib/sass/script/css_lexer.rb +8 -4
- data/lib/sass/script/css_parser.rb +5 -2
- data/lib/sass/script/functions.rb +1547 -618
- data/lib/sass/script/lexer.rb +122 -72
- data/lib/sass/script/parser.rb +304 -135
- data/lib/sass/script/tree/funcall.rb +306 -0
- data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
- 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/{node.rb → tree/node.rb} +30 -12
- data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
- data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
- data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
- data/lib/sass/script/tree/variable.rb +57 -0
- data/lib/sass/script/tree.rb +15 -0
- data/lib/sass/script/value/arg_list.rb +36 -0
- data/lib/sass/script/value/base.rb +238 -0
- data/lib/sass/script/value/bool.rb +40 -0
- data/lib/sass/script/{color.rb → value/color.rb} +256 -74
- data/lib/sass/script/value/deprecated_false.rb +55 -0
- data/lib/sass/script/value/helpers.rb +155 -0
- data/lib/sass/script/value/list.rb +128 -0
- data/lib/sass/script/value/map.rb +70 -0
- data/lib/sass/script/value/null.rb +49 -0
- data/lib/sass/script/{number.rb → value/number.rb} +115 -62
- data/lib/sass/script/{string.rb → value/string.rb} +9 -11
- data/lib/sass/script/value.rb +12 -0
- data/lib/sass/script.rb +35 -9
- data/lib/sass/scss/css_parser.rb +2 -12
- data/lib/sass/scss/parser.rb +657 -230
- data/lib/sass/scss/rx.rb +17 -12
- data/lib/sass/scss/static_parser.rb +37 -6
- data/lib/sass/scss.rb +0 -1
- data/lib/sass/selector/abstract_sequence.rb +35 -3
- data/lib/sass/selector/comma_sequence.rb +29 -14
- data/lib/sass/selector/sequence.rb +371 -74
- data/lib/sass/selector/simple.rb +28 -13
- data/lib/sass/selector/simple_sequence.rb +163 -36
- data/lib/sass/selector.rb +138 -36
- data/lib/sass/shared.rb +3 -5
- data/lib/sass/source/map.rb +196 -0
- data/lib/sass/source/position.rb +39 -0
- data/lib/sass/source/range.rb +41 -0
- data/lib/sass/stack.rb +126 -0
- data/lib/sass/supports.rb +228 -0
- data/lib/sass/tree/at_root_node.rb +82 -0
- data/lib/sass/tree/comment_node.rb +34 -29
- 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 +3 -3
- data/lib/sass/tree/directive_node.rb +33 -3
- data/lib/sass/tree/each_node.rb +9 -9
- data/lib/sass/tree/extend_node.rb +20 -6
- data/lib/sass/tree/for_node.rb +6 -6
- data/lib/sass/tree/function_node.rb +12 -4
- data/lib/sass/tree/if_node.rb +2 -15
- data/lib/sass/tree/import_node.rb +11 -5
- data/lib/sass/tree/media_node.rb +27 -11
- data/lib/sass/tree/mixin_def_node.rb +15 -4
- data/lib/sass/tree/mixin_node.rb +27 -7
- data/lib/sass/tree/node.rb +69 -35
- data/lib/sass/tree/prop_node.rb +47 -31
- data/lib/sass/tree/return_node.rb +4 -3
- data/lib/sass/tree/root_node.rb +20 -4
- data/lib/sass/tree/rule_node.rb +37 -26
- 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 +10 -4
- data/lib/sass/tree/visitors/base.rb +5 -8
- data/lib/sass/tree/visitors/check_nesting.rb +67 -52
- data/lib/sass/tree/visitors/convert.rb +134 -53
- data/lib/sass/tree/visitors/cssize.rb +245 -51
- data/lib/sass/tree/visitors/deep_copy.rb +102 -0
- data/lib/sass/tree/visitors/extend.rb +68 -0
- data/lib/sass/tree/visitors/perform.rb +331 -105
- data/lib/sass/tree/visitors/set_options.rb +125 -0
- data/lib/sass/tree/visitors/to_css.rb +259 -95
- data/lib/sass/tree/warn_node.rb +3 -3
- data/lib/sass/tree/while_node.rb +3 -3
- 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 +11 -2
- data/lib/sass/util/test.rb +9 -0
- data/lib/sass/util.rb +565 -39
- data/lib/sass/version.rb +27 -15
- data/lib/sass.rb +39 -4
- data/test/sass/cache_test.rb +15 -0
- data/test/sass/compiler_test.rb +223 -0
- data/test/sass/conversion_test.rb +901 -107
- data/test/sass/css2sass_test.rb +94 -0
- data/test/sass/engine_test.rb +1059 -164
- data/test/sass/exec_test.rb +86 -0
- data/test/sass/extend_test.rb +933 -837
- 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 +995 -136
- data/test/sass/importer_test.rb +338 -18
- data/test/sass/logger_test.rb +58 -0
- data/test/sass/more_results/more_import.css +2 -2
- data/test/sass/plugin_test.rb +114 -30
- data/test/sass/results/cached_import_option.css +3 -0
- data/test/sass/results/filename_fn.css +3 -0
- data/test/sass/results/import.css +2 -2
- data/test/sass/results/import_charset.css +1 -0
- data/test/sass/results/import_charset_1_8.css +1 -0
- data/test/sass/results/import_charset_ibm866.css +1 -0
- data/test/sass/results/import_content.css +1 -0
- data/test/sass/results/script.css +1 -1
- data/test/sass/results/scss_import.css +2 -2
- data/test/sass/results/units.css +2 -2
- data/test/sass/script_conversion_test.rb +43 -1
- data/test/sass/script_test.rb +380 -36
- data/test/sass/scss/css_test.rb +257 -75
- data/test/sass/scss/scss_test.rb +2322 -110
- data/test/sass/source_map_test.rb +887 -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_content.sass +3 -0
- data/test/sass/templates/_same_name_different_partiality.scss +1 -0
- data/test/sass/templates/bork5.sass +3 -0
- data/test/sass/templates/cached_import_option.scss +3 -0
- data/test/sass/templates/double_import_loop1.sass +1 -0
- data/test/sass/templates/filename_fn.scss +18 -0
- data/test/sass/templates/import_charset.sass +2 -0
- data/test/sass/templates/import_charset_1_8.sass +2 -0
- data/test/sass/templates/import_charset_ibm866.sass +2 -0
- data/test/sass/templates/import_content.sass +4 -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/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/test_helper.rb +1 -1
- 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_test.rb +183 -0
- data/test/sass/value_helpers_test.rb +181 -0
- data/test/test_helper.rb +45 -5
- data/vendor/listen/CHANGELOG.md +228 -0
- data/vendor/listen/CONTRIBUTING.md +38 -0
- data/vendor/listen/Gemfile +30 -0
- data/vendor/listen/Guardfile +8 -0
- data/vendor/{fssm → listen}/LICENSE +1 -1
- data/vendor/listen/README.md +315 -0
- data/vendor/listen/Rakefile +47 -0
- data/vendor/listen/Vagrantfile +96 -0
- data/vendor/listen/lib/listen/adapter.rb +214 -0
- data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
- data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
- data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
- data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
- data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
- data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
- data/vendor/listen/lib/listen/directory_record.rb +371 -0
- data/vendor/listen/lib/listen/listener.rb +225 -0
- data/vendor/listen/lib/listen/multi_listener.rb +143 -0
- data/vendor/listen/lib/listen/turnstile.rb +28 -0
- data/vendor/listen/lib/listen/version.rb +3 -0
- data/vendor/listen/lib/listen.rb +40 -0
- data/vendor/listen/listen.gemspec +22 -0
- data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
- data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
- data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
- data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
- data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
- data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
- data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
- data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
- data/vendor/listen/spec/listen/listener_spec.rb +169 -0
- data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
- data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
- data/vendor/listen/spec/listen_spec.rb +73 -0
- data/vendor/listen/spec/spec_helper.rb +21 -0
- data/vendor/listen/spec/support/adapter_helper.rb +629 -0
- data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
- data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
- data/vendor/listen/spec/support/listeners_helper.rb +156 -0
- data/vendor/listen/spec/support/platform_helper.rb +15 -0
- metadata +344 -271
- data/lib/sass/less.rb +0 -382
- data/lib/sass/script/bool.rb +0 -18
- data/lib/sass/script/funcall.rb +0 -162
- data/lib/sass/script/list.rb +0 -76
- data/lib/sass/script/literal.rb +0 -245
- data/lib/sass/script/variable.rb +0 -54
- data/lib/sass/scss/sass_parser.rb +0 -11
- data/test/sass/less_conversion_test.rb +0 -653
- data/vendor/fssm/README.markdown +0 -55
- data/vendor/fssm/Rakefile +0 -59
- data/vendor/fssm/VERSION.yml +0 -5
- data/vendor/fssm/example.rb +0 -9
- data/vendor/fssm/fssm.gemspec +0 -77
- data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
- data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
- data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
- data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
- data/vendor/fssm/lib/fssm/monitor.rb +0 -26
- data/vendor/fssm/lib/fssm/path.rb +0 -91
- data/vendor/fssm/lib/fssm/pathname.rb +0 -502
- data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
- data/vendor/fssm/lib/fssm/state/file.rb +0 -24
- data/vendor/fssm/lib/fssm/support.rb +0 -63
- data/vendor/fssm/lib/fssm/tree.rb +0 -176
- data/vendor/fssm/lib/fssm.rb +0 -33
- data/vendor/fssm/profile/prof-cache.rb +0 -40
- data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
- data/vendor/fssm/profile/prof-pathname.rb +0 -68
- data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
- data/vendor/fssm/profile/prof.html +0 -2379
- data/vendor/fssm/spec/path_spec.rb +0 -75
- data/vendor/fssm/spec/root/duck/quack.txt +0 -0
- data/vendor/fssm/spec/root/file.css +0 -0
- data/vendor/fssm/spec/root/file.rb +0 -0
- data/vendor/fssm/spec/root/file.yml +0 -0
- data/vendor/fssm/spec/root/moo/cow.txt +0 -0
- data/vendor/fssm/spec/spec_helper.rb +0 -14
@@ -2,13 +2,14 @@
|
|
2
2
|
class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
|
3
3
|
protected
|
4
4
|
|
5
|
+
def initialize
|
6
|
+
@parents = []
|
7
|
+
end
|
8
|
+
|
5
9
|
def visit(node)
|
6
|
-
if error =
|
7
|
-
|
8
|
-
|
9
|
-
(@real_parent && (
|
10
|
-
try_send("invalid_#{node_name @real_parent}_real_child?", @real_parent, node) ||
|
11
|
-
try_send("invalid_#{node_name node}_real_parent?", @real_parent, node)))
|
10
|
+
if (error = @parent && (
|
11
|
+
try_send(@parent.class.invalid_child_method_name, @parent, node) ||
|
12
|
+
try_send(node.class.invalid_parent_method_name, @parent, node)))
|
12
13
|
raise Sass::SyntaxError.new(error)
|
13
14
|
end
|
14
15
|
super
|
@@ -17,16 +18,18 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
|
|
17
18
|
raise e
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
CONTROL_NODES = [Sass::Tree::EachNode, Sass::Tree::ForNode, Sass::Tree::IfNode,
|
22
|
+
Sass::Tree::WhileNode, Sass::Tree::TraceNode]
|
23
|
+
SCRIPT_NODES = [Sass::Tree::ImportNode] + CONTROL_NODES
|
22
24
|
def visit_children(parent)
|
23
25
|
old_parent = @parent
|
24
|
-
@parent = parent unless is_any_of?(parent,
|
25
|
-
|
26
|
+
@parent = parent unless is_any_of?(parent, SCRIPT_NODES) ||
|
27
|
+
(parent.bubbles? && !old_parent.is_a?(Sass::Tree::RootNode))
|
28
|
+
@parents.push parent
|
26
29
|
super
|
27
30
|
ensure
|
28
31
|
@parent = old_parent
|
29
|
-
@
|
32
|
+
@parents.pop
|
30
33
|
end
|
31
34
|
|
32
35
|
def visit_root(node)
|
@@ -44,72 +47,85 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
|
|
44
47
|
raise e
|
45
48
|
end
|
46
49
|
|
47
|
-
def
|
48
|
-
|
50
|
+
def visit_mixindef(node)
|
51
|
+
@current_mixin_def, old_mixin_def = node, @current_mixin_def
|
52
|
+
yield
|
53
|
+
ensure
|
54
|
+
@current_mixin_def = old_mixin_def
|
49
55
|
end
|
50
56
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
57
|
+
def invalid_content_parent?(parent, child)
|
58
|
+
if @current_mixin_def
|
59
|
+
@current_mixin_def.has_content = true
|
60
|
+
nil
|
61
|
+
else
|
62
|
+
"@content may only be used within a mixin."
|
55
63
|
end
|
56
64
|
end
|
57
65
|
|
58
|
-
def
|
59
|
-
"
|
66
|
+
def invalid_charset_parent?(parent, child)
|
67
|
+
"@charset may only be used at the root of a document." unless parent.is_a?(Sass::Tree::RootNode)
|
60
68
|
end
|
61
69
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
]
|
67
|
-
def invalid_function_child?(parent, child)
|
68
|
-
unless is_any_of?(child, INVALID_FUNCTION_CHILDREN)
|
69
|
-
"Functions can only contain variable declarations and control directives."
|
70
|
+
VALID_EXTEND_PARENTS = [Sass::Tree::RuleNode, Sass::Tree::MixinDefNode, Sass::Tree::MixinNode]
|
71
|
+
def invalid_extend_parent?(parent, child)
|
72
|
+
unless is_any_of?(parent, VALID_EXTEND_PARENTS)
|
73
|
+
return "Extend directives may only be used within rules."
|
70
74
|
end
|
71
75
|
end
|
72
76
|
|
73
|
-
INVALID_IMPORT_PARENTS =
|
74
|
-
Sass::Tree::
|
75
|
-
Sass::Tree::EachNode, Sass::Tree::MixinDefNode
|
76
|
-
]
|
77
|
+
INVALID_IMPORT_PARENTS = CONTROL_NODES +
|
78
|
+
[Sass::Tree::MixinDefNode, Sass::Tree::MixinNode]
|
77
79
|
def invalid_import_parent?(parent, child)
|
78
|
-
|
80
|
+
unless (@parents.map {|p| p.class} & INVALID_IMPORT_PARENTS).empty?
|
79
81
|
return "Import directives may not be used within control directives or mixins."
|
80
82
|
end
|
81
83
|
return if parent.is_a?(Sass::Tree::RootNode)
|
82
84
|
return "CSS import directives may only be used at the root of a document." if child.css_import?
|
83
|
-
# If this is a nested @import, we need to make sure it doesn't have anything
|
84
|
-
# that's legal at top-level but not in the current context (e.g. mixin defs).
|
85
|
-
child.imported_file.to_tree.children.each {|c| visit(c)}
|
86
|
-
nil
|
87
85
|
rescue Sass::SyntaxError => e
|
88
86
|
e.modify_backtrace(:filename => child.imported_file.options[:filename])
|
89
87
|
e.add_backtrace(:filename => child.filename, :line => child.line)
|
90
88
|
raise e
|
91
89
|
end
|
92
90
|
|
93
|
-
def
|
94
|
-
|
91
|
+
def invalid_mixindef_parent?(parent, child)
|
92
|
+
unless (@parents.map {|p| p.class} & INVALID_IMPORT_PARENTS).empty?
|
93
|
+
return "Mixins may not be defined within control directives or other mixins."
|
94
|
+
end
|
95
95
|
end
|
96
96
|
|
97
|
-
def
|
98
|
-
|
97
|
+
def invalid_function_parent?(parent, child)
|
98
|
+
unless (@parents.map {|p| p.class} & INVALID_IMPORT_PARENTS).empty?
|
99
|
+
return "Functions may not be defined within control directives or other mixins."
|
100
|
+
end
|
99
101
|
end
|
100
102
|
|
101
|
-
|
103
|
+
VALID_FUNCTION_CHILDREN = [
|
104
|
+
Sass::Tree::CommentNode, Sass::Tree::DebugNode, Sass::Tree::ReturnNode,
|
105
|
+
Sass::Tree::VariableNode, Sass::Tree::WarnNode
|
106
|
+
] + CONTROL_NODES
|
107
|
+
def invalid_function_child?(parent, child)
|
108
|
+
unless is_any_of?(child, VALID_FUNCTION_CHILDREN)
|
109
|
+
"Functions can only contain variable declarations and control directives."
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
VALID_PROP_CHILDREN = CONTROL_NODES + [Sass::Tree::CommentNode,
|
114
|
+
Sass::Tree::PropNode,
|
115
|
+
Sass::Tree::MixinNode]
|
102
116
|
def invalid_prop_child?(parent, child)
|
103
|
-
unless is_any_of?(child,
|
117
|
+
unless is_any_of?(child, VALID_PROP_CHILDREN)
|
104
118
|
"Illegal nesting: Only properties may be nested beneath properties."
|
105
119
|
end
|
106
120
|
end
|
107
121
|
|
108
|
-
|
109
|
-
|
122
|
+
VALID_PROP_PARENTS = [Sass::Tree::RuleNode, Sass::Tree::PropNode,
|
123
|
+
Sass::Tree::MixinDefNode, Sass::Tree::DirectiveNode,
|
124
|
+
Sass::Tree::MixinNode]
|
110
125
|
def invalid_prop_parent?(parent, child)
|
111
|
-
unless is_any_of?(parent,
|
112
|
-
"Properties are only allowed within rules, directives, or other properties." +
|
126
|
+
unless is_any_of?(parent, VALID_PROP_PARENTS)
|
127
|
+
"Properties are only allowed within rules, directives, mixin includes, or other properties." +
|
128
|
+
child.pseudo_class_selector_message
|
113
129
|
end
|
114
130
|
end
|
115
131
|
|
@@ -120,15 +136,14 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
|
|
120
136
|
private
|
121
137
|
|
122
138
|
def is_any_of?(val, classes)
|
123
|
-
|
139
|
+
classes.each do |c|
|
124
140
|
return true if val.is_a?(c)
|
125
141
|
end
|
126
|
-
|
142
|
+
false
|
127
143
|
end
|
128
144
|
|
129
|
-
def try_send(method, *args
|
130
|
-
return unless respond_to?(method)
|
131
|
-
send(method, *args
|
145
|
+
def try_send(method, *args)
|
146
|
+
return unless respond_to?(method, true)
|
147
|
+
send(method, *args)
|
132
148
|
end
|
133
149
|
end
|
134
|
-
|
@@ -16,12 +16,18 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
16
16
|
@options = options
|
17
17
|
@format = format
|
18
18
|
@tabs = 0
|
19
|
+
# 2 spaces by default
|
20
|
+
@tab_chars = @options[:indent] || " "
|
19
21
|
end
|
20
22
|
|
21
23
|
def visit_children(parent)
|
22
24
|
@tabs += 1
|
23
25
|
return @format == :sass ? "\n" : " {}\n" if parent.children.empty?
|
24
|
-
|
26
|
+
if @format == :sass
|
27
|
+
"\n" + super.join.rstrip + "\n"
|
28
|
+
else
|
29
|
+
" {\n" + super.join.rstrip + "\n#{ @tab_chars * (@tabs - 1)}}\n"
|
30
|
+
end
|
25
31
|
ensure
|
26
32
|
@tabs -= 1
|
27
33
|
end
|
@@ -32,7 +38,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
32
38
|
visit(child) +
|
33
39
|
if nxt &&
|
34
40
|
(child.is_a?(Sass::Tree::CommentNode) &&
|
35
|
-
child.line + child.
|
41
|
+
child.line + child.lines + 1 == nxt.line) ||
|
36
42
|
(child.is_a?(Sass::Tree::ImportNode) && nxt.is_a?(Sass::Tree::ImportNode) &&
|
37
43
|
child.line + 1 == nxt.line) ||
|
38
44
|
(child.is_a?(Sass::Tree::VariableNode) && nxt.is_a?(Sass::Tree::VariableNode) &&
|
@@ -49,8 +55,9 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
49
55
|
end
|
50
56
|
|
51
57
|
def visit_comment(node)
|
52
|
-
|
53
|
-
|
58
|
+
value = interp_to_src(node.value)
|
59
|
+
if @format == :sass
|
60
|
+
content = value.gsub(/\*\/$/, '').rstrip
|
54
61
|
if content =~ /\A[ \t]/
|
55
62
|
# Re-indent SCSS comments like this:
|
56
63
|
# /* foo
|
@@ -60,38 +67,27 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
60
67
|
content.sub!(/\A([ \t]*)\/\*/, '/*\1')
|
61
68
|
end
|
62
69
|
|
63
|
-
content
|
64
|
-
|
65
|
-
|
70
|
+
if content.include?("\n")
|
71
|
+
content.gsub!(/\n \*/, "\n ")
|
72
|
+
spaces = content.scan(/\n( *)/).map {|s| s.first.size}.min
|
73
|
+
sep = node.type == :silent ? "\n//" : "\n *"
|
74
|
+
if spaces >= 2
|
75
|
+
content.gsub!(/\n /, sep)
|
66
76
|
else
|
67
|
-
content.gsub!(/\n
|
68
|
-
spaces = content.scan(/\n( *)/).map {|s| s.first.size}.min
|
69
|
-
sep = node.silent ? "\n//" : "\n *"
|
70
|
-
if spaces >= 2
|
71
|
-
content.gsub(/\n /, sep)
|
72
|
-
else
|
73
|
-
content.gsub(/\n#{' ' * spaces}/, sep)
|
74
|
-
end
|
77
|
+
content.gsub!(/\n#{' ' * spaces}/, sep)
|
75
78
|
end
|
79
|
+
end
|
76
80
|
|
77
|
-
content.gsub!(/\A\/\*/, '//') if node.silent
|
81
|
+
content.gsub!(/\A\/\*/, '//') if node.type == :silent
|
78
82
|
content.gsub!(/^/, tab_str)
|
79
|
-
content.rstrip + "\n"
|
83
|
+
content = content.rstrip + "\n"
|
80
84
|
else
|
81
|
-
spaces = (
|
82
|
-
content = if node.silent
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
content
|
88
|
-
end
|
89
|
-
if node.loud
|
90
|
-
if node.silent
|
91
|
-
content.gsub!(%r{^\s*(//!?)}, '//!')
|
92
|
-
else
|
93
|
-
content.sub!(%r{^\s*(/\*)}, '/*!')
|
94
|
-
end
|
85
|
+
spaces = (@tab_chars * [@tabs - value[/^ */].size, 0].max)
|
86
|
+
content = if node.type == :silent
|
87
|
+
value.gsub(/^[\/ ]\*/, '//').gsub(/ *\*\/$/, '')
|
88
|
+
else
|
89
|
+
value
|
90
|
+
end.gsub(/^/, spaces) + "\n"
|
95
91
|
end
|
96
92
|
content
|
97
93
|
end
|
@@ -101,17 +97,20 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
101
97
|
end
|
102
98
|
|
103
99
|
def visit_directive(node)
|
104
|
-
res = "#{tab_str}#{node.value}"
|
100
|
+
res = "#{tab_str}#{interp_to_src(node.value)}"
|
101
|
+
res.gsub!(/^@import \#\{(.*)\}([^}]*)$/, '@import \1\2')
|
105
102
|
return res + "#{semi}\n" unless node.has_children
|
106
103
|
res + yield + "\n"
|
107
104
|
end
|
108
105
|
|
109
106
|
def visit_each(node)
|
110
|
-
|
107
|
+
vars = node.vars.map {|var| "$#{dasherize(var)}"}.join(", ")
|
108
|
+
"#{tab_str}@each #{vars} in #{node.list.to_sass(@options)}#{yield}"
|
111
109
|
end
|
112
110
|
|
113
111
|
def visit_extend(node)
|
114
|
-
"#{tab_str}@extend #{selector_to_src(node.selector).lstrip}#{semi}
|
112
|
+
"#{tab_str}@extend #{selector_to_src(node.selector).lstrip}#{semi}" +
|
113
|
+
"#{" !optional" if node.optional?}\n"
|
115
114
|
end
|
116
115
|
|
117
116
|
def visit_for(node)
|
@@ -123,16 +122,24 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
123
122
|
args = node.args.map do |v, d|
|
124
123
|
d ? "#{v.to_sass(@options)}: #{d.to_sass(@options)}" : v.to_sass(@options)
|
125
124
|
end.join(", ")
|
125
|
+
if node.splat
|
126
|
+
args << ", " unless node.args.empty?
|
127
|
+
args << node.splat.to_sass(@options) << "..."
|
128
|
+
end
|
126
129
|
|
127
130
|
"#{tab_str}@function #{dasherize(node.name)}(#{args})#{yield}"
|
128
131
|
end
|
129
132
|
|
130
133
|
def visit_if(node)
|
131
134
|
name =
|
132
|
-
if !@is_else
|
133
|
-
|
134
|
-
|
135
|
+
if !@is_else
|
136
|
+
"if"
|
137
|
+
elsif node.expr
|
138
|
+
"else if"
|
139
|
+
else
|
140
|
+
"else"
|
135
141
|
end
|
142
|
+
@is_else = false
|
136
143
|
str = "#{tab_str}@#{name}"
|
137
144
|
str << " #{node.expr.to_sass(@options)}" if node.expr
|
138
145
|
str << yield
|
@@ -149,33 +156,73 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
149
156
|
end
|
150
157
|
|
151
158
|
def visit_media(node)
|
152
|
-
"#{tab_str}@media #{node.query}#{yield}"
|
159
|
+
"#{tab_str}@media #{query_interp_to_src(node.query)}#{yield}"
|
160
|
+
end
|
161
|
+
|
162
|
+
def visit_supports(node)
|
163
|
+
"#{tab_str}@#{node.name} #{node.condition.to_src(@options)}#{yield}"
|
164
|
+
end
|
165
|
+
|
166
|
+
def visit_cssimport(node)
|
167
|
+
if node.uri.is_a?(Sass::Script::Tree::Node)
|
168
|
+
str = "#{tab_str}@import #{node.uri.to_sass(@options)}"
|
169
|
+
else
|
170
|
+
str = "#{tab_str}@import #{node.uri}"
|
171
|
+
end
|
172
|
+
str << " #{interp_to_src(node.query)}" unless node.query.empty?
|
173
|
+
"#{str}#{semi}\n"
|
153
174
|
end
|
154
175
|
|
155
176
|
def visit_mixindef(node)
|
156
177
|
args =
|
157
|
-
if node.args.empty?
|
178
|
+
if node.args.empty? && node.splat.nil?
|
158
179
|
""
|
159
180
|
else
|
160
|
-
'('
|
181
|
+
str = '('
|
182
|
+
str << node.args.map do |v, d|
|
161
183
|
if d
|
162
184
|
"#{v.to_sass(@options)}: #{d.to_sass(@options)}"
|
163
185
|
else
|
164
186
|
v.to_sass(@options)
|
165
187
|
end
|
166
|
-
end.join(", ")
|
188
|
+
end.join(", ")
|
189
|
+
|
190
|
+
if node.splat
|
191
|
+
str << ", " unless node.args.empty?
|
192
|
+
str << node.splat.to_sass(@options) << '...'
|
193
|
+
end
|
194
|
+
|
195
|
+
str << ')'
|
167
196
|
end
|
168
|
-
|
197
|
+
|
169
198
|
"#{tab_str}#{@format == :sass ? '=' : '@mixin '}#{dasherize(node.name)}#{args}#{yield}"
|
170
199
|
end
|
171
200
|
|
172
201
|
def visit_mixin(node)
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
202
|
+
arg_to_sass = lambda do |arg|
|
203
|
+
sass = arg.to_sass(@options)
|
204
|
+
sass = "(#{sass})" if arg.is_a?(Sass::Script::Tree::ListLiteral) && arg.separator == :comma
|
205
|
+
sass
|
177
206
|
end
|
178
|
-
|
207
|
+
|
208
|
+
unless node.args.empty? && node.keywords.empty? && node.splat.nil?
|
209
|
+
args = node.args.map(&arg_to_sass)
|
210
|
+
keywords = Sass::Util.hash_to_a(node.keywords.as_stored).
|
211
|
+
map {|k, v| "$#{dasherize(k)}: #{arg_to_sass[v]}"}
|
212
|
+
|
213
|
+
if node.splat
|
214
|
+
splat = "#{arg_to_sass[node.splat]}..."
|
215
|
+
kwarg_splat = "#{arg_to_sass[node.kwarg_splat]}..." if node.kwarg_splat
|
216
|
+
end
|
217
|
+
|
218
|
+
arglist = "(#{[args, splat, keywords, kwarg_splat].flatten.compact.join(', ')})"
|
219
|
+
end
|
220
|
+
"#{tab_str}#{@format == :sass ? '+' : '@include '}" +
|
221
|
+
"#{dasherize(node.name)}#{arglist}#{node.has_children ? yield : semi}\n"
|
222
|
+
end
|
223
|
+
|
224
|
+
def visit_content(node)
|
225
|
+
"#{tab_str}@content#{semi}\n"
|
179
226
|
end
|
180
227
|
|
181
228
|
def visit_prop(node)
|
@@ -196,7 +243,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
196
243
|
elsif @format == :scss
|
197
244
|
name = selector_to_scss(node.rule)
|
198
245
|
res = name + yield
|
199
|
-
if node.children.last.is_a?(Sass::Tree::CommentNode) && node.children.last.silent
|
246
|
+
if node.children.last.is_a?(Sass::Tree::CommentNode) && node.children.last.type == :silent
|
200
247
|
res.slice!(-3..-1)
|
201
248
|
res << "\n" << tab_str << "}\n"
|
202
249
|
end
|
@@ -205,7 +252,8 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
205
252
|
end
|
206
253
|
|
207
254
|
def visit_variable(node)
|
208
|
-
"#{tab_str}$#{dasherize(node.name)}: #{node.expr.to_sass(@options)}
|
255
|
+
"#{tab_str}$#{dasherize(node.name)}: #{node.expr.to_sass(@options)}" +
|
256
|
+
"#{' !global' if node.global}#{' !default' if node.guarded}#{semi}\n"
|
209
257
|
end
|
210
258
|
|
211
259
|
def visit_warn(node)
|
@@ -216,8 +264,42 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
216
264
|
"#{tab_str}@while #{node.expr.to_sass(@options)}#{yield}"
|
217
265
|
end
|
218
266
|
|
267
|
+
def visit_atroot(node)
|
268
|
+
if node.query
|
269
|
+
"#{tab_str}@at-root #{query_interp_to_src(node.query)}#{yield}"
|
270
|
+
elsif node.children.length == 1 && node.children.first.is_a?(Sass::Tree::RuleNode)
|
271
|
+
rule = node.children.first
|
272
|
+
"#{tab_str}@at-root #{selector_to_src(rule.rule)}#{visit_children(rule)}"
|
273
|
+
else
|
274
|
+
"#{tab_str}@at-root#{yield}"
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
219
278
|
private
|
220
279
|
|
280
|
+
def interp_to_src(interp)
|
281
|
+
interp.map do |r|
|
282
|
+
next r if r.is_a?(String)
|
283
|
+
"\#{#{r.to_sass(@options)}}"
|
284
|
+
end.join
|
285
|
+
end
|
286
|
+
|
287
|
+
# Like interp_to_src, but removes the unnecessary `#{}` around the keys and
|
288
|
+
# values in query expressions.
|
289
|
+
def query_interp_to_src(interp)
|
290
|
+
Sass::Util.enum_with_index(interp).map do |r, i|
|
291
|
+
next r if r.is_a?(String)
|
292
|
+
before, after = interp[i - 1], interp[i + 1]
|
293
|
+
if before.is_a?(String) && after.is_a?(String) &&
|
294
|
+
((before[-1] == ?( && after[0] == ?:) ||
|
295
|
+
(before =~ /:\s*/ && after[0] == ?)))
|
296
|
+
r.to_sass(@options)
|
297
|
+
else
|
298
|
+
"\#{#{r.to_sass(@options)}}"
|
299
|
+
end
|
300
|
+
end.join
|
301
|
+
end
|
302
|
+
|
221
303
|
def selector_to_src(sel)
|
222
304
|
@format == :sass ? selector_to_sass(sel) : selector_to_scss(sel)
|
223
305
|
end
|
@@ -225,7 +307,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
225
307
|
def selector_to_sass(sel)
|
226
308
|
sel.map do |r|
|
227
309
|
if r.is_a?(String)
|
228
|
-
r.gsub(/(,[ \t]*)
|
310
|
+
r.gsub(/(,)?([ \t]*)\n\s*/) {$1 ? "#{$1}#{$2}\n" : " "}
|
229
311
|
else
|
230
312
|
"\#{#{r.to_sass(@options)}}"
|
231
313
|
end
|
@@ -233,8 +315,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
233
315
|
end
|
234
316
|
|
235
317
|
def selector_to_scss(sel)
|
236
|
-
sel.
|
237
|
-
join.gsub(/^[ \t]*/, tab_str)
|
318
|
+
interp_to_src(sel).gsub(/^[ \t]*/, tab_str).gsub(/[ \t]*$/, '')
|
238
319
|
end
|
239
320
|
|
240
321
|
def semi
|
@@ -242,7 +323,7 @@ class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
|
|
242
323
|
end
|
243
324
|
|
244
325
|
def tab_str
|
245
|
-
|
326
|
+
@tab_chars * @tabs
|
246
327
|
end
|
247
328
|
|
248
329
|
def dasherize(s)
|