sass4 4.0.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 +13 -0
- data/AGENTS.md +534 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/CONTRIBUTING.md +148 -0
- data/MIT-LICENSE +20 -0
- data/README.md +242 -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/sass-spec-ref.sh +40 -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 +46 -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/deprecation.rb +55 -0
- data/lib/sass/engine.rb +1236 -0
- data/lib/sass/environment.rb +236 -0
- data/lib/sass/error.rb +198 -0
- data/lib/sass/exec/base.rb +188 -0
- data/lib/sass/exec/sass_convert.rb +283 -0
- data/lib/sass/exec/sass_scss.rb +436 -0
- data/lib/sass/exec.rb +9 -0
- data/lib/sass/features.rb +48 -0
- data/lib/sass/importers/base.rb +182 -0
- data/lib/sass/importers/deprecated_path.rb +51 -0
- data/lib/sass/importers/filesystem.rb +221 -0
- data/lib/sass/importers.rb +23 -0
- data/lib/sass/logger/base.rb +47 -0
- data/lib/sass/logger/delayed.rb +50 -0
- data/lib/sass/logger/log_level.rb +45 -0
- data/lib/sass/logger.rb +17 -0
- data/lib/sass/media.rb +210 -0
- data/lib/sass/plugin/compiler.rb +552 -0
- data/lib/sass/plugin/configuration.rb +134 -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 +134 -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 +36 -0
- data/lib/sass/script/functions.rb +3103 -0
- data/lib/sass/script/lexer.rb +518 -0
- data/lib/sass/script/parser.rb +1164 -0
- data/lib/sass/script/tree/funcall.rb +314 -0
- data/lib/sass/script/tree/interpolation.rb +220 -0
- data/lib/sass/script/tree/list_literal.rb +119 -0
- data/lib/sass/script/tree/literal.rb +49 -0
- data/lib/sass/script/tree/map_literal.rb +64 -0
- data/lib/sass/script/tree/node.rb +119 -0
- data/lib/sass/script/tree/operation.rb +149 -0
- data/lib/sass/script/tree/selector.rb +26 -0
- data/lib/sass/script/tree/string_interpolation.rb +125 -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 +258 -0
- data/lib/sass/script/value/bool.rb +35 -0
- data/lib/sass/script/value/callable.rb +25 -0
- data/lib/sass/script/value/color.rb +704 -0
- data/lib/sass/script/value/function.rb +19 -0
- data/lib/sass/script/value/helpers.rb +298 -0
- data/lib/sass/script/value/list.rb +135 -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 +564 -0
- data/lib/sass/script/value/string.rb +138 -0
- data/lib/sass/script/value.rb +13 -0
- data/lib/sass/script.rb +66 -0
- data/lib/sass/scss/css_parser.rb +61 -0
- data/lib/sass/scss/parser.rb +1343 -0
- data/lib/sass/scss/rx.rb +134 -0
- data/lib/sass/scss/static_parser.rb +351 -0
- data/lib/sass/scss.rb +14 -0
- data/lib/sass/selector/abstract_sequence.rb +112 -0
- data/lib/sass/selector/comma_sequence.rb +195 -0
- data/lib/sass/selector/pseudo.rb +291 -0
- data/lib/sass/selector/sequence.rb +661 -0
- data/lib/sass/selector/simple.rb +124 -0
- data/lib/sass/selector/simple_sequence.rb +348 -0
- data/lib/sass/selector.rb +327 -0
- data/lib/sass/shared.rb +76 -0
- data/lib/sass/source/map.rb +209 -0
- data/lib/sass/source/position.rb +39 -0
- data/lib/sass/source/range.rb +41 -0
- data/lib/sass/stack.rb +140 -0
- data/lib/sass/supports.rb +225 -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 +68 -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 +44 -0
- data/lib/sass/tree/if_node.rb +52 -0
- data/lib/sass/tree/import_node.rb +75 -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 +240 -0
- data/lib/sass/tree/prop_node.rb +162 -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 +153 -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 +173 -0
- data/lib/sass/tree/visitors/convert.rb +350 -0
- data/lib/sass/tree/visitors/cssize.rb +362 -0
- data/lib/sass/tree/visitors/deep_copy.rb +107 -0
- data/lib/sass/tree/visitors/extend.rb +64 -0
- data/lib/sass/tree/visitors/perform.rb +572 -0
- data/lib/sass/tree/visitors/set_options.rb +139 -0
- data/lib/sass/tree/visitors/to_css.rb +440 -0
- data/lib/sass/tree/warn_node.rb +18 -0
- data/lib/sass/tree/while_node.rb +18 -0
- data/lib/sass/util/multibyte_string_scanner.rb +151 -0
- data/lib/sass/util/normalized_map.rb +122 -0
- data/lib/sass/util/subset_map.rb +109 -0
- data/lib/sass/util/test.rb +9 -0
- data/lib/sass/util.rb +1137 -0
- data/lib/sass/version.rb +120 -0
- data/lib/sass.rb +102 -0
- data/rails/init.rb +1 -0
- metadata +283 -0
data/lib/sass/stack.rb
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
module Sass
|
|
2
|
+
# A class representing the stack when compiling a Sass file.
|
|
3
|
+
class Stack
|
|
4
|
+
# TODO: use this to generate stack information for Sass::SyntaxErrors.
|
|
5
|
+
|
|
6
|
+
# A single stack frame.
|
|
7
|
+
class Frame
|
|
8
|
+
# The filename of the file in which this stack frame was created.
|
|
9
|
+
#
|
|
10
|
+
# @return [String]
|
|
11
|
+
attr_reader :filename
|
|
12
|
+
|
|
13
|
+
# The line number on which this stack frame was created.
|
|
14
|
+
#
|
|
15
|
+
# @return [String]
|
|
16
|
+
attr_reader :line
|
|
17
|
+
|
|
18
|
+
# The type of this stack frame. This can be `:import`, `:mixin`, or
|
|
19
|
+
# `:base`.
|
|
20
|
+
#
|
|
21
|
+
# `:base` indicates that this is the bottom-most frame, meaning that it
|
|
22
|
+
# represents a single line of code rather than a nested context. The stack
|
|
23
|
+
# will only ever have one base frame, and it will always be the most
|
|
24
|
+
# deeply-nested frame.
|
|
25
|
+
#
|
|
26
|
+
# @return [Symbol?]
|
|
27
|
+
attr_reader :type
|
|
28
|
+
|
|
29
|
+
# The name of the stack frame. For mixin frames, this is the mixin name;
|
|
30
|
+
# otherwise, it's `nil`.
|
|
31
|
+
#
|
|
32
|
+
# @return [String?]
|
|
33
|
+
attr_reader :name
|
|
34
|
+
|
|
35
|
+
def initialize(filename, line, type, name = nil)
|
|
36
|
+
@filename = filename
|
|
37
|
+
@line = line
|
|
38
|
+
@type = type
|
|
39
|
+
@name = name
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Whether this frame represents an import.
|
|
43
|
+
#
|
|
44
|
+
# @return [Boolean]
|
|
45
|
+
def is_import?
|
|
46
|
+
type == :import
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Whether this frame represents a mixin.
|
|
50
|
+
#
|
|
51
|
+
# @return [Boolean]
|
|
52
|
+
def is_mixin?
|
|
53
|
+
type == :mixin
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Whether this is the base frame.
|
|
57
|
+
#
|
|
58
|
+
# @return [Boolean]
|
|
59
|
+
def is_base?
|
|
60
|
+
type == :base
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# The stack frames. The last frame is the most deeply-nested.
|
|
65
|
+
#
|
|
66
|
+
# @return [Array<Frame>]
|
|
67
|
+
attr_reader :frames
|
|
68
|
+
|
|
69
|
+
def initialize
|
|
70
|
+
@frames = []
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Pushes a base frame onto the stack.
|
|
74
|
+
#
|
|
75
|
+
# @param filename [String] See \{Frame#filename}.
|
|
76
|
+
# @param line [String] See \{Frame#line}.
|
|
77
|
+
# @yield [] A block in which the new frame is on the stack.
|
|
78
|
+
def with_base(filename, line)
|
|
79
|
+
with_frame(filename, line, :base) {yield}
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Pushes an import frame onto the stack.
|
|
83
|
+
#
|
|
84
|
+
# @param filename [String] See \{Frame#filename}.
|
|
85
|
+
# @param line [String] See \{Frame#line}.
|
|
86
|
+
# @yield [] A block in which the new frame is on the stack.
|
|
87
|
+
def with_import(filename, line)
|
|
88
|
+
with_frame(filename, line, :import) {yield}
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Pushes a mixin frame onto the stack.
|
|
92
|
+
#
|
|
93
|
+
# @param filename [String] See \{Frame#filename}.
|
|
94
|
+
# @param line [String] See \{Frame#line}.
|
|
95
|
+
# @param name [String] See \{Frame#name}.
|
|
96
|
+
# @yield [] A block in which the new frame is on the stack.
|
|
97
|
+
def with_mixin(filename, line, name)
|
|
98
|
+
with_frame(filename, line, :mixin, name) {yield}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Pushes a function frame onto the stack.
|
|
102
|
+
#
|
|
103
|
+
# @param filename [String] See \{Frame#filename}.
|
|
104
|
+
# @param line [String] See \{Frame#line}.
|
|
105
|
+
# @param name [String] See \{Frame#name}.
|
|
106
|
+
# @yield [] A block in which the new frame is on the stack.
|
|
107
|
+
def with_function(filename, line, name)
|
|
108
|
+
with_frame(filename, line, :function, name) {yield}
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Pushes a function frame onto the stack.
|
|
112
|
+
#
|
|
113
|
+
# @param filename [String] See \{Frame#filename}.
|
|
114
|
+
# @param line [String] See \{Frame#line}.
|
|
115
|
+
# @param name [String] See \{Frame#name}.
|
|
116
|
+
# @yield [] A block in which the new frame is on the stack.
|
|
117
|
+
def with_directive(filename, line, name)
|
|
118
|
+
with_frame(filename, line, :directive, name) {yield}
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def to_s
|
|
122
|
+
(frames.reverse + [nil]).each_cons(2).each_with_index.
|
|
123
|
+
map do |(frame, caller), i|
|
|
124
|
+
"#{i == 0 ? 'on' : 'from'} line #{frame.line}" +
|
|
125
|
+
" of #{frame.filename || 'an unknown file'}" +
|
|
126
|
+
(caller && caller.name ? ", in `#{caller.name}'" : "")
|
|
127
|
+
end.join("\n")
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
private
|
|
131
|
+
|
|
132
|
+
def with_frame(filename, line, type, name = nil)
|
|
133
|
+
@frames.pop if @frames.last && @frames.last.type == :base
|
|
134
|
+
@frames.push(Frame.new(filename, line, type, name))
|
|
135
|
+
yield
|
|
136
|
+
ensure
|
|
137
|
+
@frames.pop unless type == :base && @frames.last && @frames.last.type != :base
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# A namespace for the `@supports` condition parse tree.
|
|
2
|
+
module Sass::Supports
|
|
3
|
+
# The abstract superclass of all Supports conditions.
|
|
4
|
+
class Condition
|
|
5
|
+
# Runs the SassScript in the supports condition.
|
|
6
|
+
#
|
|
7
|
+
# @param environment [Sass::Environment] The environment in which to run the script.
|
|
8
|
+
def perform(environment); Sass::Util.abstract(self); end
|
|
9
|
+
|
|
10
|
+
# Returns the CSS for this condition.
|
|
11
|
+
#
|
|
12
|
+
# @return [String]
|
|
13
|
+
def to_css; Sass::Util.abstract(self); end
|
|
14
|
+
|
|
15
|
+
# Returns the Sass/CSS code for this condition.
|
|
16
|
+
#
|
|
17
|
+
# @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize}).
|
|
18
|
+
# @return [String]
|
|
19
|
+
def to_src(options); Sass::Util.abstract(self); end
|
|
20
|
+
|
|
21
|
+
# Returns a deep copy of this condition and all its children.
|
|
22
|
+
#
|
|
23
|
+
# @return [Condition]
|
|
24
|
+
def deep_copy; Sass::Util.abstract(self); end
|
|
25
|
+
|
|
26
|
+
# Sets the options hash for the script nodes in the supports condition.
|
|
27
|
+
#
|
|
28
|
+
# @param options [{Symbol => Object}] The options has to set.
|
|
29
|
+
def options=(options); Sass::Util.abstract(self); end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# An operator condition (e.g. `CONDITION1 and CONDITION2`).
|
|
33
|
+
class Operator < Condition
|
|
34
|
+
# The left-hand condition.
|
|
35
|
+
#
|
|
36
|
+
# @return [Sass::Supports::Condition]
|
|
37
|
+
attr_accessor :left
|
|
38
|
+
|
|
39
|
+
# The right-hand condition.
|
|
40
|
+
#
|
|
41
|
+
# @return [Sass::Supports::Condition]
|
|
42
|
+
attr_accessor :right
|
|
43
|
+
|
|
44
|
+
# The operator ("and" or "or").
|
|
45
|
+
#
|
|
46
|
+
# @return [String]
|
|
47
|
+
attr_accessor :op
|
|
48
|
+
|
|
49
|
+
def initialize(left, right, op)
|
|
50
|
+
@left = left
|
|
51
|
+
@right = right
|
|
52
|
+
@op = op
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def perform(env)
|
|
56
|
+
@left.perform(env)
|
|
57
|
+
@right.perform(env)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def to_css
|
|
61
|
+
"#{parens @left, @left.to_css} #{op} #{parens @right, @right.to_css}"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def to_src(options)
|
|
65
|
+
"#{parens @left, @left.to_src(options)} #{op} #{parens @right, @right.to_src(options)}"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def deep_copy
|
|
69
|
+
copy = dup
|
|
70
|
+
copy.left = @left.deep_copy
|
|
71
|
+
copy.right = @right.deep_copy
|
|
72
|
+
copy
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def options=(options)
|
|
76
|
+
@left.options = options
|
|
77
|
+
@right.options = options
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def parens(condition, str)
|
|
83
|
+
if condition.is_a?(Negation) || (condition.is_a?(Operator) && condition.op != op)
|
|
84
|
+
return "(#{str})"
|
|
85
|
+
else
|
|
86
|
+
return str
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# A negation condition (`not CONDITION`).
|
|
92
|
+
class Negation < Condition
|
|
93
|
+
# The condition being negated.
|
|
94
|
+
#
|
|
95
|
+
# @return [Sass::Supports::Condition]
|
|
96
|
+
attr_accessor :condition
|
|
97
|
+
|
|
98
|
+
def initialize(condition)
|
|
99
|
+
@condition = condition
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def perform(env)
|
|
103
|
+
@condition.perform(env)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def to_css
|
|
107
|
+
"not #{parens @condition.to_css}"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def to_src(options)
|
|
111
|
+
"not #{parens @condition.to_src(options)}"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def deep_copy
|
|
115
|
+
copy = dup
|
|
116
|
+
copy.condition = condition.deep_copy
|
|
117
|
+
copy
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def options=(options)
|
|
121
|
+
condition.options = options
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
private
|
|
125
|
+
|
|
126
|
+
def parens(str)
|
|
127
|
+
return "(#{str})" if @condition.is_a?(Negation) || @condition.is_a?(Operator)
|
|
128
|
+
str
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# A declaration condition (e.g. `(feature: value)`).
|
|
133
|
+
class Declaration < Condition
|
|
134
|
+
# @return [Sass::Script::Tree::Node] The feature name.
|
|
135
|
+
attr_accessor :name
|
|
136
|
+
|
|
137
|
+
# @!attribute resolved_name
|
|
138
|
+
# The name of the feature after any SassScript has been resolved.
|
|
139
|
+
# Only set once \{Tree::Visitors::Perform} has been run.
|
|
140
|
+
#
|
|
141
|
+
# @return [String]
|
|
142
|
+
attr_accessor :resolved_name
|
|
143
|
+
|
|
144
|
+
# The feature value.
|
|
145
|
+
#
|
|
146
|
+
# @return [Sass::Script::Tree::Node]
|
|
147
|
+
attr_accessor :value
|
|
148
|
+
|
|
149
|
+
# The value of the feature after any SassScript has been resolved.
|
|
150
|
+
# Only set once \{Tree::Visitors::Perform} has been run.
|
|
151
|
+
#
|
|
152
|
+
# @return [String]
|
|
153
|
+
attr_accessor :resolved_value
|
|
154
|
+
|
|
155
|
+
def initialize(name, value)
|
|
156
|
+
@name = name
|
|
157
|
+
@value = value
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def perform(env)
|
|
161
|
+
@resolved_name = name.perform(env)
|
|
162
|
+
@resolved_value = value.perform(env)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def to_css
|
|
166
|
+
"(#{@resolved_name}: #{@resolved_value})"
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def to_src(options)
|
|
170
|
+
"(#{@name.to_sass(options)}: #{@value.to_sass(options)})"
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def deep_copy
|
|
174
|
+
copy = dup
|
|
175
|
+
copy.name = @name.deep_copy
|
|
176
|
+
copy.value = @value.deep_copy
|
|
177
|
+
copy
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def options=(options)
|
|
181
|
+
@name.options = options
|
|
182
|
+
@value.options = options
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# An interpolation condition (e.g. `#{$var}`).
|
|
187
|
+
class Interpolation < Condition
|
|
188
|
+
# The SassScript expression in the interpolation.
|
|
189
|
+
#
|
|
190
|
+
# @return [Sass::Script::Tree::Node]
|
|
191
|
+
attr_accessor :value
|
|
192
|
+
|
|
193
|
+
# The value of the expression after it's been resolved.
|
|
194
|
+
# Only set once \{Tree::Visitors::Perform} has been run.
|
|
195
|
+
#
|
|
196
|
+
# @return [String]
|
|
197
|
+
attr_accessor :resolved_value
|
|
198
|
+
|
|
199
|
+
def initialize(value)
|
|
200
|
+
@value = value
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def perform(env)
|
|
204
|
+
@resolved_value = value.perform(env).to_s(:quote => :none)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def to_css
|
|
208
|
+
@resolved_value
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def to_src(options)
|
|
212
|
+
@value.to_sass(options)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def deep_copy
|
|
216
|
+
copy = dup
|
|
217
|
+
copy.value = @value.deep_copy
|
|
218
|
+
copy
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def options=(options)
|
|
222
|
+
@value.options = options
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module Sass
|
|
2
|
+
module Tree
|
|
3
|
+
# A dynamic node representing an `@at-root` directive.
|
|
4
|
+
#
|
|
5
|
+
# An `@at-root` directive with a selector is converted to an \{AtRootNode}
|
|
6
|
+
# containing a \{RuleNode} at parse time.
|
|
7
|
+
#
|
|
8
|
+
# @see Sass::Tree
|
|
9
|
+
class AtRootNode < Node
|
|
10
|
+
# The query for this node (e.g. `(without: media)`),
|
|
11
|
+
# interspersed with {Sass::Script::Tree::Node}s representing
|
|
12
|
+
# `#{}`-interpolation. Any adjacent strings will be merged
|
|
13
|
+
# together.
|
|
14
|
+
#
|
|
15
|
+
# This will be nil if the directive didn't have a query. In this
|
|
16
|
+
# case, {#resolved\_type} will automatically be set to
|
|
17
|
+
# `:without` and {#resolved\_rule} will automatically be set to `["rule"]`.
|
|
18
|
+
#
|
|
19
|
+
# @return [Array<String, Sass::Script::Tree::Node>]
|
|
20
|
+
attr_accessor :query
|
|
21
|
+
|
|
22
|
+
# The resolved type of this directive. `:with` or `:without`.
|
|
23
|
+
#
|
|
24
|
+
# @return [Symbol]
|
|
25
|
+
attr_accessor :resolved_type
|
|
26
|
+
|
|
27
|
+
# The resolved value of this directive -- a list of directives
|
|
28
|
+
# to either include or exclude.
|
|
29
|
+
#
|
|
30
|
+
# @return [Array<String>]
|
|
31
|
+
attr_accessor :resolved_value
|
|
32
|
+
|
|
33
|
+
# The number of additional tabs that the contents of this node
|
|
34
|
+
# should be indented.
|
|
35
|
+
#
|
|
36
|
+
# @return [Number]
|
|
37
|
+
attr_accessor :tabs
|
|
38
|
+
|
|
39
|
+
# Whether the last child of this node should be considered the
|
|
40
|
+
# end of a group.
|
|
41
|
+
#
|
|
42
|
+
# @return [Boolean]
|
|
43
|
+
attr_accessor :group_end
|
|
44
|
+
|
|
45
|
+
def initialize(query = nil)
|
|
46
|
+
super()
|
|
47
|
+
@query = Sass::Util.strip_string_array(Sass::Util.merge_adjacent_strings(query)) if query
|
|
48
|
+
@tabs = 0
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Returns whether or not the given directive is excluded by this
|
|
52
|
+
# node. `directive` may be "rule", which indicates whether
|
|
53
|
+
# normal CSS rules should be excluded.
|
|
54
|
+
#
|
|
55
|
+
# @param directive [String]
|
|
56
|
+
# @return [Boolean]
|
|
57
|
+
def exclude?(directive)
|
|
58
|
+
if resolved_type == :with
|
|
59
|
+
return false if resolved_value.include?('all')
|
|
60
|
+
!resolved_value.include?(directive)
|
|
61
|
+
else # resolved_type == :without
|
|
62
|
+
return true if resolved_value.include?('all')
|
|
63
|
+
resolved_value.include?(directive)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Returns whether the given node is excluded by this node.
|
|
68
|
+
#
|
|
69
|
+
# @param node [Sass::Tree::Node]
|
|
70
|
+
# @return [Boolean]
|
|
71
|
+
def exclude_node?(node)
|
|
72
|
+
return exclude?(node.name.gsub(/^@/, '')) if node.is_a?(Sass::Tree::DirectiveNode)
|
|
73
|
+
return exclude?('keyframes') if node.is_a?(Sass::Tree::KeyframeRuleNode)
|
|
74
|
+
exclude?('rule') && node.is_a?(Sass::Tree::RuleNode)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# @see Node#bubbles?
|
|
78
|
+
def bubbles?
|
|
79
|
+
true
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Sass::Tree
|
|
2
|
+
# A static node representing an unprocessed Sass `@charset` directive.
|
|
3
|
+
#
|
|
4
|
+
# @see Sass::Tree
|
|
5
|
+
class CharsetNode < Node
|
|
6
|
+
# The name of the charset.
|
|
7
|
+
#
|
|
8
|
+
# @return [String]
|
|
9
|
+
attr_accessor :name
|
|
10
|
+
|
|
11
|
+
# @param name [String] see \{#name}
|
|
12
|
+
def initialize(name)
|
|
13
|
+
@name = name
|
|
14
|
+
super()
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @see Node#invisible?
|
|
18
|
+
def invisible?
|
|
19
|
+
true
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'sass/tree/node'
|
|
2
|
+
|
|
3
|
+
module Sass::Tree
|
|
4
|
+
# A static node representing a Sass comment (silent or loud).
|
|
5
|
+
#
|
|
6
|
+
# @see Sass::Tree
|
|
7
|
+
class CommentNode < Node
|
|
8
|
+
# The text of the comment, not including `/*` and `*/`.
|
|
9
|
+
# Interspersed with {Sass::Script::Tree::Node}s representing `#{}`-interpolation
|
|
10
|
+
# if this is a loud comment.
|
|
11
|
+
#
|
|
12
|
+
# @return [Array<String, Sass::Script::Tree::Node>]
|
|
13
|
+
attr_accessor :value
|
|
14
|
+
|
|
15
|
+
# The text of the comment
|
|
16
|
+
# after any interpolated SassScript has been resolved.
|
|
17
|
+
# Only set once \{Tree::Visitors::Perform} has been run.
|
|
18
|
+
#
|
|
19
|
+
# @return [String]
|
|
20
|
+
attr_accessor :resolved_value
|
|
21
|
+
|
|
22
|
+
# The type of the comment. `:silent` means it's never output to CSS,
|
|
23
|
+
# `:normal` means it's output in every compile mode except `:compressed`,
|
|
24
|
+
# and `:loud` means it's output even in `:compressed`.
|
|
25
|
+
#
|
|
26
|
+
# @return [Symbol]
|
|
27
|
+
attr_accessor :type
|
|
28
|
+
|
|
29
|
+
# @param value [Array<String, Sass::Script::Tree::Node>] See \{#value}
|
|
30
|
+
# @param type [Symbol] See \{#type}
|
|
31
|
+
def initialize(value, type)
|
|
32
|
+
@value = Sass::Util.with_extracted_values(value) {|str| normalize_indentation str}
|
|
33
|
+
@type = type
|
|
34
|
+
super()
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Compares the contents of two comments.
|
|
38
|
+
#
|
|
39
|
+
# @param other [Object] The object to compare with
|
|
40
|
+
# @return [Boolean] Whether or not this node and the other object
|
|
41
|
+
# are the same
|
|
42
|
+
def ==(other)
|
|
43
|
+
self.class == other.class && value == other.value && type == other.type
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns `true` if this is a silent comment
|
|
47
|
+
# or the current style doesn't render comments.
|
|
48
|
+
#
|
|
49
|
+
# Comments starting with ! are never invisible (and the ! is removed from the output.)
|
|
50
|
+
#
|
|
51
|
+
# @return [Boolean]
|
|
52
|
+
def invisible?
|
|
53
|
+
case @type
|
|
54
|
+
when :loud; false
|
|
55
|
+
when :silent; true
|
|
56
|
+
else; style == :compressed
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Returns the number of lines in the comment.
|
|
61
|
+
#
|
|
62
|
+
# @return [Integer]
|
|
63
|
+
def lines
|
|
64
|
+
@value.inject(0) do |s, e|
|
|
65
|
+
next s + e.count("\n") if e.is_a?(String)
|
|
66
|
+
next s
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def normalize_indentation(str)
|
|
73
|
+
ind = str.split("\n").inject(str[/^[ \t]*/].split("")) do |pre, line|
|
|
74
|
+
line[/^[ \t]*/].split("").zip(pre).inject([]) do |arr, (a, b)|
|
|
75
|
+
break arr if a != b
|
|
76
|
+
arr << a
|
|
77
|
+
end
|
|
78
|
+
end.join
|
|
79
|
+
str.gsub(/^#{ind}/, '')
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module Sass::Tree
|
|
2
|
+
# A node representing an `@import` rule that's importing plain CSS.
|
|
3
|
+
#
|
|
4
|
+
# @see Sass::Tree
|
|
5
|
+
class CssImportNode < DirectiveNode
|
|
6
|
+
# The URI being imported, either as a plain string or an interpolated
|
|
7
|
+
# script string.
|
|
8
|
+
#
|
|
9
|
+
# @return [String, Sass::Script::Tree::Node]
|
|
10
|
+
attr_accessor :uri
|
|
11
|
+
|
|
12
|
+
# The text of the URI being imported after any interpolated SassScript has
|
|
13
|
+
# been resolved. Only set once {Tree::Visitors::Perform} has been run.
|
|
14
|
+
#
|
|
15
|
+
# @return [String]
|
|
16
|
+
attr_accessor :resolved_uri
|
|
17
|
+
|
|
18
|
+
# The supports condition for this import.
|
|
19
|
+
#
|
|
20
|
+
# @return [Sass::Supports::Condition]
|
|
21
|
+
attr_accessor :supports_condition
|
|
22
|
+
|
|
23
|
+
# The media query for this rule, interspersed with
|
|
24
|
+
# {Sass::Script::Tree::Node}s representing `#{}`-interpolation. Any adjacent
|
|
25
|
+
# strings will be merged together.
|
|
26
|
+
#
|
|
27
|
+
# @return [Array<String, Sass::Script::Tree::Node>]
|
|
28
|
+
attr_accessor :query
|
|
29
|
+
|
|
30
|
+
# The media query for this rule, without any unresolved interpolation.
|
|
31
|
+
# It's only set once {Tree::Visitors::Perform} has been run.
|
|
32
|
+
#
|
|
33
|
+
# @return [Sass::Media::QueryList]
|
|
34
|
+
attr_accessor :resolved_query
|
|
35
|
+
|
|
36
|
+
# @param uri [String, Sass::Script::Tree::Node] See \{#uri}
|
|
37
|
+
# @param query [Array<String, Sass::Script::Tree::Node>] See \{#query}
|
|
38
|
+
# @param supports_condition [Sass::Supports::Condition] See \{#supports_condition}
|
|
39
|
+
def initialize(uri, query = [], supports_condition = nil)
|
|
40
|
+
@uri = uri
|
|
41
|
+
@query = query
|
|
42
|
+
@supports_condition = supports_condition
|
|
43
|
+
super('')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @param uri [String] See \{#resolved_uri}
|
|
47
|
+
# @return [CssImportNode]
|
|
48
|
+
def self.resolved(uri)
|
|
49
|
+
node = new(uri)
|
|
50
|
+
node.resolved_uri = uri
|
|
51
|
+
node
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @see DirectiveNode#value
|
|
55
|
+
def value; raise NotImplementedError; end
|
|
56
|
+
|
|
57
|
+
# @see DirectiveNode#resolved_value
|
|
58
|
+
def resolved_value
|
|
59
|
+
@resolved_value ||=
|
|
60
|
+
begin
|
|
61
|
+
str = "@import #{resolved_uri}"
|
|
62
|
+
str << " supports(#{supports_condition.to_css})" if supports_condition
|
|
63
|
+
str << " #{resolved_query.to_css}" if resolved_query
|
|
64
|
+
str
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Sass
|
|
2
|
+
module Tree
|
|
3
|
+
# A dynamic node representing a Sass `@debug` statement.
|
|
4
|
+
#
|
|
5
|
+
# @see Sass::Tree
|
|
6
|
+
class DebugNode < Node
|
|
7
|
+
# The expression to print.
|
|
8
|
+
# @return [Script::Tree::Node]
|
|
9
|
+
attr_accessor :expr
|
|
10
|
+
|
|
11
|
+
# @param expr [Script::Tree::Node] The expression to print
|
|
12
|
+
def initialize(expr)
|
|
13
|
+
@expr = expr
|
|
14
|
+
super()
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Sass::Tree
|
|
2
|
+
# A static node representing an unprocessed Sass `@`-directive.
|
|
3
|
+
# Directives known to Sass, like `@for` and `@debug`,
|
|
4
|
+
# are handled by their own nodes;
|
|
5
|
+
# only CSS directives like `@media` and `@font-face` become {DirectiveNode}s.
|
|
6
|
+
#
|
|
7
|
+
# `@import` and `@charset` are special cases;
|
|
8
|
+
# they become {ImportNode}s and {CharsetNode}s, respectively.
|
|
9
|
+
#
|
|
10
|
+
# @see Sass::Tree
|
|
11
|
+
class DirectiveNode < Node
|
|
12
|
+
# The text of the directive, `@` and all, with interpolation included.
|
|
13
|
+
#
|
|
14
|
+
# @return [Array<String, Sass::Script::Tree::Node>]
|
|
15
|
+
attr_accessor :value
|
|
16
|
+
|
|
17
|
+
# The text of the directive after any interpolated SassScript has been resolved.
|
|
18
|
+
# Only set once \{Tree::Visitors::Perform} has been run.
|
|
19
|
+
#
|
|
20
|
+
# @return [String]
|
|
21
|
+
attr_accessor :resolved_value
|
|
22
|
+
|
|
23
|
+
# @see RuleNode#tabs
|
|
24
|
+
attr_accessor :tabs
|
|
25
|
+
|
|
26
|
+
# @see RuleNode#group_end
|
|
27
|
+
attr_accessor :group_end
|
|
28
|
+
|
|
29
|
+
# @param value [Array<String, Sass::Script::Tree::Node>] See \{#value}
|
|
30
|
+
def initialize(value)
|
|
31
|
+
@value = value
|
|
32
|
+
@tabs = 0
|
|
33
|
+
super()
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @param value [String] See \{#resolved_value}
|
|
37
|
+
# @return [DirectiveNode]
|
|
38
|
+
def self.resolved(value)
|
|
39
|
+
node = new([value])
|
|
40
|
+
node.resolved_value = value
|
|
41
|
+
node
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @return [String] The name of the directive, including `@`.
|
|
45
|
+
def name
|
|
46
|
+
@name ||= value.first.gsub(/ .*$/, '')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Strips out any vendor prefixes and downcases the directive name.
|
|
50
|
+
# @return [String] The normalized name of the directive.
|
|
51
|
+
def normalized_name
|
|
52
|
+
@normalized_name ||= name.gsub(/^(@)(?:-[a-zA-Z0-9]+-)?/, '\1').downcase
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def bubbles?
|
|
56
|
+
has_children
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|