oreorenasass 3.4.4 → 3.4.5
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 +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +50 -70
- data/Rakefile +5 -26
- data/VERSION +1 -1
- data/VERSION_NAME +1 -1
- data/bin/sass +1 -1
- data/bin/scss +1 -1
- data/lib/sass.rb +12 -19
- data/lib/sass/cache_stores/base.rb +2 -2
- data/lib/sass/cache_stores/chain.rb +1 -2
- data/lib/sass/cache_stores/filesystem.rb +5 -1
- data/lib/sass/cache_stores/memory.rb +1 -1
- data/lib/sass/cache_stores/null.rb +2 -2
- data/lib/sass/callbacks.rb +0 -1
- data/lib/sass/css.rb +13 -11
- data/lib/sass/engine.rb +173 -424
- data/lib/sass/environment.rb +58 -148
- data/lib/sass/error.rb +14 -11
- data/lib/sass/exec.rb +703 -5
- data/lib/sass/importers/base.rb +6 -49
- data/lib/sass/importers/filesystem.rb +19 -44
- data/lib/sass/logger.rb +4 -1
- data/lib/sass/logger/base.rb +4 -2
- data/lib/sass/logger/log_level.rb +7 -3
- data/lib/sass/media.rb +23 -20
- data/lib/sass/plugin.rb +7 -7
- data/lib/sass/plugin/compiler.rb +145 -304
- data/lib/sass/plugin/configuration.rb +23 -18
- data/lib/sass/plugin/merb.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +3 -3
- data/lib/sass/repl.rb +3 -3
- data/lib/sass/script.rb +8 -35
- data/lib/sass/script/{value/arg_list.rb → arg_list.rb} +25 -9
- data/lib/sass/script/bool.rb +18 -0
- data/lib/sass/script/color.rb +606 -0
- data/lib/sass/script/css_lexer.rb +4 -8
- data/lib/sass/script/css_parser.rb +2 -5
- data/lib/sass/script/funcall.rb +245 -0
- data/lib/sass/script/functions.rb +408 -1491
- data/lib/sass/script/interpolation.rb +79 -0
- data/lib/sass/script/lexer.rb +68 -172
- data/lib/sass/script/list.rb +85 -0
- data/lib/sass/script/literal.rb +221 -0
- data/lib/sass/script/{tree/node.rb → node.rb} +12 -22
- data/lib/sass/script/{value/null.rb → null.rb} +7 -14
- data/lib/sass/script/{value/number.rb → number.rb} +75 -152
- data/lib/sass/script/{tree/operation.rb → operation.rb} +24 -17
- data/lib/sass/script/parser.rb +110 -245
- data/lib/sass/script/string.rb +51 -0
- data/lib/sass/script/{tree/string_interpolation.rb → string_interpolation.rb} +4 -5
- data/lib/sass/script/{tree/unary_operation.rb → unary_operation.rb} +6 -6
- data/lib/sass/script/variable.rb +58 -0
- data/lib/sass/scss/css_parser.rb +3 -9
- data/lib/sass/scss/parser.rb +421 -450
- data/lib/sass/scss/rx.rb +11 -19
- data/lib/sass/scss/static_parser.rb +7 -321
- data/lib/sass/selector.rb +194 -68
- data/lib/sass/selector/abstract_sequence.rb +14 -29
- data/lib/sass/selector/comma_sequence.rb +25 -108
- data/lib/sass/selector/sequence.rb +66 -159
- data/lib/sass/selector/simple.rb +25 -23
- data/lib/sass/selector/simple_sequence.rb +63 -173
- data/lib/sass/shared.rb +1 -1
- data/lib/sass/supports.rb +15 -13
- data/lib/sass/tree/charset_node.rb +1 -1
- data/lib/sass/tree/comment_node.rb +3 -3
- data/lib/sass/tree/css_import_node.rb +11 -11
- data/lib/sass/tree/debug_node.rb +2 -2
- data/lib/sass/tree/directive_node.rb +4 -21
- data/lib/sass/tree/each_node.rb +8 -8
- data/lib/sass/tree/extend_node.rb +7 -14
- data/lib/sass/tree/for_node.rb +4 -4
- data/lib/sass/tree/function_node.rb +4 -9
- data/lib/sass/tree/if_node.rb +1 -1
- data/lib/sass/tree/import_node.rb +5 -4
- data/lib/sass/tree/media_node.rb +14 -4
- data/lib/sass/tree/mixin_def_node.rb +4 -4
- data/lib/sass/tree/mixin_node.rb +8 -21
- data/lib/sass/tree/node.rb +12 -54
- data/lib/sass/tree/prop_node.rb +20 -39
- data/lib/sass/tree/return_node.rb +2 -3
- data/lib/sass/tree/root_node.rb +3 -19
- data/lib/sass/tree/rule_node.rb +22 -35
- data/lib/sass/tree/supports_node.rb +13 -0
- data/lib/sass/tree/trace_node.rb +1 -2
- data/lib/sass/tree/variable_node.rb +3 -9
- data/lib/sass/tree/visitors/base.rb +8 -5
- data/lib/sass/tree/visitors/check_nesting.rb +19 -49
- data/lib/sass/tree/visitors/convert.rb +56 -74
- data/lib/sass/tree/visitors/cssize.rb +74 -202
- data/lib/sass/tree/visitors/deep_copy.rb +5 -10
- data/lib/sass/tree/visitors/extend.rb +7 -7
- data/lib/sass/tree/visitors/perform.rb +185 -278
- data/lib/sass/tree/visitors/set_options.rb +6 -20
- data/lib/sass/tree/visitors/to_css.rb +81 -234
- data/lib/sass/tree/warn_node.rb +2 -2
- data/lib/sass/tree/while_node.rb +2 -2
- data/lib/sass/util.rb +152 -522
- data/lib/sass/util/multibyte_string_scanner.rb +0 -2
- data/lib/sass/util/subset_map.rb +3 -4
- data/lib/sass/util/test.rb +1 -0
- data/lib/sass/version.rb +22 -20
- data/test/Gemfile +3 -0
- data/test/Gemfile.lock +10 -0
- data/test/sass/cache_test.rb +20 -62
- data/test/sass/callbacks_test.rb +1 -1
- data/test/sass/conversion_test.rb +2 -296
- data/test/sass/css2sass_test.rb +4 -23
- data/test/sass/engine_test.rb +354 -411
- data/test/sass/exec_test.rb +2 -2
- data/test/sass/extend_test.rb +145 -324
- data/test/sass/functions_test.rb +86 -873
- data/test/sass/importer_test.rb +21 -241
- data/test/sass/logger_test.rb +1 -1
- data/test/sass/more_results/more_import.css +1 -1
- data/test/sass/plugin_test.rb +26 -16
- data/test/sass/results/compact.css +1 -1
- data/test/sass/results/complex.css +4 -4
- data/test/sass/results/expanded.css +1 -1
- data/test/sass/results/import.css +1 -1
- data/test/sass/results/import_charset_ibm866.css +2 -2
- data/test/sass/results/mixins.css +17 -17
- data/test/sass/results/nested.css +1 -1
- data/test/sass/results/parent_ref.css +2 -2
- data/test/sass/results/script.css +3 -3
- data/test/sass/results/scss_import.css +1 -1
- data/test/sass/script_conversion_test.rb +7 -36
- data/test/sass/script_test.rb +53 -485
- data/test/sass/scss/css_test.rb +28 -143
- data/test/sass/scss/rx_test.rb +4 -4
- data/test/sass/scss/scss_test.rb +325 -2119
- data/test/sass/templates/scss_import.scss +1 -2
- data/test/sass/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
- data/test/sass/util/subset_map_test.rb +2 -2
- data/test/sass/util_test.rb +1 -86
- data/test/test_helper.rb +8 -37
- metadata +19 -66
- data/lib/sass/exec/base.rb +0 -187
- data/lib/sass/exec/sass_convert.rb +0 -264
- data/lib/sass/exec/sass_scss.rb +0 -424
- data/lib/sass/features.rb +0 -47
- data/lib/sass/script/tree.rb +0 -16
- data/lib/sass/script/tree/funcall.rb +0 -306
- data/lib/sass/script/tree/interpolation.rb +0 -118
- data/lib/sass/script/tree/list_literal.rb +0 -77
- data/lib/sass/script/tree/literal.rb +0 -45
- data/lib/sass/script/tree/map_literal.rb +0 -64
- data/lib/sass/script/tree/selector.rb +0 -26
- data/lib/sass/script/tree/variable.rb +0 -57
- data/lib/sass/script/value.rb +0 -11
- data/lib/sass/script/value/base.rb +0 -240
- data/lib/sass/script/value/bool.rb +0 -35
- data/lib/sass/script/value/color.rb +0 -680
- data/lib/sass/script/value/helpers.rb +0 -262
- data/lib/sass/script/value/list.rb +0 -113
- data/lib/sass/script/value/map.rb +0 -70
- data/lib/sass/script/value/string.rb +0 -97
- data/lib/sass/selector/pseudo.rb +0 -256
- data/lib/sass/source/map.rb +0 -210
- data/lib/sass/source/position.rb +0 -39
- data/lib/sass/source/range.rb +0 -41
- data/lib/sass/stack.rb +0 -120
- data/lib/sass/tree/at_root_node.rb +0 -83
- data/lib/sass/tree/error_node.rb +0 -18
- data/lib/sass/tree/keyframe_rule_node.rb +0 -15
- data/lib/sass/util/cross_platform_random.rb +0 -19
- data/lib/sass/util/normalized_map.rb +0 -130
- data/lib/sass/util/ordered_hash.rb +0 -192
- data/test/sass/compiler_test.rb +0 -232
- data/test/sass/encoding_test.rb +0 -219
- data/test/sass/source_map_test.rb +0 -977
- data/test/sass/superselector_test.rb +0 -191
- data/test/sass/util/normalized_map_test.rb +0 -51
- data/test/sass/value_helpers_test.rb +0 -179
data/lib/sass/scss/rx.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
1
|
module Sass
|
3
2
|
module SCSS
|
4
3
|
# A module containing regular expressions used
|
@@ -23,7 +22,7 @@ module Sass
|
|
23
22
|
out << escape_char(value.slice!(0...1))
|
24
23
|
end
|
25
24
|
out << value.gsub(/[^a-zA-Z0-9_-]/) {|c| escape_char c}
|
26
|
-
out
|
25
|
+
return out
|
27
26
|
end
|
28
27
|
|
29
28
|
# Escapes a single character for a CSS identifier.
|
@@ -33,7 +32,7 @@ module Sass
|
|
33
32
|
# @private
|
34
33
|
def self.escape_char(c)
|
35
34
|
return "\\%06x" % Sass::Util.ord(c) unless c =~ /[ -\/:-~]/
|
36
|
-
"\\#{c}"
|
35
|
+
return "\\#{c}"
|
37
36
|
end
|
38
37
|
|
39
38
|
# Creates a Regexp from a plain text string,
|
@@ -64,9 +63,9 @@ module Sass
|
|
64
63
|
STRING1 = /\"((?:[^\n\r\f\\"]|\\#{NL}|#{ESCAPE})*)\"/
|
65
64
|
STRING2 = /\'((?:[^\n\r\f\\']|\\#{NL}|#{ESCAPE})*)\'/
|
66
65
|
|
67
|
-
IDENT =
|
66
|
+
IDENT = /-?#{NMSTART}#{NMCHAR}*/
|
68
67
|
NAME = /#{NMCHAR}+/
|
69
|
-
NUM =
|
68
|
+
NUM = /[0-9]+|[0-9]*\.[0-9]+/
|
70
69
|
STRING = /#{STRING1}|#{STRING2}/
|
71
70
|
URLCHAR = /[#%&*-~]|#{NONASCII}|#{ESCAPE}/
|
72
71
|
URL = /(#{URLCHAR}*)/
|
@@ -81,8 +80,8 @@ module Sass
|
|
81
80
|
|
82
81
|
S = /[ \t\r\n\f]+/
|
83
82
|
|
84
|
-
COMMENT =
|
85
|
-
SINGLE_LINE_COMMENT =
|
83
|
+
COMMENT = /\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\//
|
84
|
+
SINGLE_LINE_COMMENT = /\/\/.*(\n[ \t]*\/\/.*)*/
|
86
85
|
|
87
86
|
CDO = quote("<!--")
|
88
87
|
CDC = quote("-->")
|
@@ -95,10 +94,9 @@ module Sass
|
|
95
94
|
HASH = /##{NAME}/
|
96
95
|
|
97
96
|
IMPORTANT = /!#{W}important/i
|
97
|
+
DEFAULT = /!#{W}default/i
|
98
98
|
|
99
|
-
|
100
|
-
NUMBER = /#{UNITLESS_NUMBER}(?:#{IDENT}|%)?/
|
101
|
-
PERCENTAGE = /#{UNITLESS_NUMBER}%/
|
99
|
+
NUMBER = /#{NUM}(?:#{IDENT}|%)?/
|
102
100
|
|
103
101
|
URI = /url\(#{W}(?:#{STRING}|#{URL})#{W}\)/i
|
104
102
|
FUNCTION = /#{IDENT}\(/
|
@@ -121,21 +119,15 @@ module Sass
|
|
121
119
|
INTERP_START = /#\{/
|
122
120
|
ANY = /:(-[-\w]+-)?any\(/i
|
123
121
|
OPTIONAL = /!#{W}optional/i
|
124
|
-
IDENT_START = /-|#{NMSTART}/
|
125
|
-
|
126
|
-
# A unit is like an IDENT, but disallows a hyphen followed by a digit.
|
127
|
-
# This allows "1px-2px" to be interpreted as subtraction rather than "1"
|
128
|
-
# with the unit "px-2px". It also allows "%".
|
129
|
-
UNIT = /-?#{NMSTART}(?:[a-zA-Z0-9_]|#{NONASCII}|#{ESCAPE}|-(?!\d))*|%/
|
130
122
|
|
131
123
|
IDENT_HYPHEN_INTERP = /-(#\{)/
|
132
|
-
STRING1_NOINTERP = /\"((?:[^\n\r\f\\"#]|#(?!\{)|#{ESCAPE})*)\"/
|
133
|
-
STRING2_NOINTERP = /\'((?:[^\n\r\f\\'#]|#(?!\{)|#{ESCAPE})*)\'/
|
124
|
+
STRING1_NOINTERP = /\"((?:[^\n\r\f\\"#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\"/
|
125
|
+
STRING2_NOINTERP = /\'((?:[^\n\r\f\\'#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\'/
|
134
126
|
STRING_NOINTERP = /#{STRING1_NOINTERP}|#{STRING2_NOINTERP}/
|
135
127
|
|
136
128
|
STATIC_COMPONENT = /#{IDENT}|#{STRING_NOINTERP}|#{HEXCOLOR}|[+-]?#{NUMBER}|\!important/i
|
137
129
|
STATIC_VALUE = /#{STATIC_COMPONENT}(\s*[\s,\/]\s*#{STATIC_COMPONENT})*([;}])/i
|
138
|
-
STATIC_SELECTOR = /(#{NMCHAR}|[ \t]|[,>+*]|[:#.]#{NMSTART}){
|
130
|
+
STATIC_SELECTOR = /(#{NMCHAR}|[ \t]|[,>+*]|[:#.]#{NMSTART}){0,50}([{])/i
|
139
131
|
end
|
140
132
|
end
|
141
133
|
end
|
@@ -24,343 +24,29 @@ module Sass
|
|
24
24
|
seq
|
25
25
|
end
|
26
26
|
|
27
|
-
# Parses a static at-root query.
|
28
|
-
#
|
29
|
-
# @return [(Symbol, Array<String>)] The type of the query
|
30
|
-
# (`:with` or `:without`) and the values that are being filtered.
|
31
|
-
# @raise [Sass::SyntaxError] if there's a syntax error in the query,
|
32
|
-
# or if it doesn't take up the entire input string.
|
33
|
-
def parse_static_at_root_query
|
34
|
-
init_scanner!
|
35
|
-
tok!(/\(/); ss
|
36
|
-
type = tok!(/\b(without|with)\b/).to_sym; ss
|
37
|
-
tok!(/:/); ss
|
38
|
-
directives = expr!(:at_root_directive_list); ss
|
39
|
-
tok!(/\)/)
|
40
|
-
expected("@at-root query list") unless @scanner.eos?
|
41
|
-
return type, directives
|
42
|
-
end
|
43
|
-
|
44
|
-
def parse_keyframes_selector
|
45
|
-
init_scanner!
|
46
|
-
sel = expr!(:keyframes_selector)
|
47
|
-
expected("keyframes selector") unless @scanner.eos?
|
48
|
-
sel
|
49
|
-
end
|
50
|
-
|
51
|
-
# @see Parser#initialize
|
52
|
-
# @param allow_parent_ref [Boolean] Whether to allow the
|
53
|
-
# parent-reference selector, `&`, when parsing the document.
|
54
|
-
# @comment
|
55
|
-
# rubocop:disable ParameterLists
|
56
|
-
def initialize(str, filename, importer, line = 1, offset = 1, allow_parent_ref = true)
|
57
|
-
# rubocop:enable ParameterLists
|
58
|
-
super(str, filename, importer, line, offset)
|
59
|
-
@allow_parent_ref = allow_parent_ref
|
60
|
-
end
|
61
|
-
|
62
27
|
private
|
63
28
|
|
64
29
|
def moz_document_function
|
65
|
-
val = tok(URI) || tok(URL_PREFIX) || tok(DOMAIN) ||
|
66
|
-
|
30
|
+
return unless val = tok(URI) || tok(URL_PREFIX) || tok(DOMAIN) ||
|
31
|
+
function(!:allow_var)
|
67
32
|
ss
|
68
33
|
[val]
|
69
34
|
end
|
70
35
|
|
71
36
|
def variable; nil; end
|
72
37
|
def script_value; nil; end
|
73
|
-
def interpolation
|
38
|
+
def interpolation; nil; end
|
74
39
|
def var_expr; nil; end
|
75
|
-
def interp_string;
|
76
|
-
def interp_uri;
|
77
|
-
def interp_ident(ident = IDENT);
|
40
|
+
def interp_string; s = tok(STRING) and [s]; end
|
41
|
+
def interp_uri; s = tok(URI) and [s]; end
|
42
|
+
def interp_ident(ident = IDENT); s = tok(ident) and [s]; end
|
78
43
|
def use_css_import?; true; end
|
79
44
|
|
80
|
-
def special_directive(name
|
45
|
+
def special_directive(name)
|
81
46
|
return unless %w[media import charset -moz-document].include?(name)
|
82
47
|
super
|
83
48
|
end
|
84
49
|
|
85
|
-
def selector_comma_sequence
|
86
|
-
sel = selector
|
87
|
-
return unless sel
|
88
|
-
selectors = [sel]
|
89
|
-
ws = ''
|
90
|
-
while tok(/,/)
|
91
|
-
ws << str {ss}
|
92
|
-
if (sel = selector)
|
93
|
-
selectors << sel
|
94
|
-
if ws.include?("\n")
|
95
|
-
selectors[-1] = Selector::Sequence.new(["\n"] + selectors.last.members)
|
96
|
-
end
|
97
|
-
ws = ''
|
98
|
-
end
|
99
|
-
end
|
100
|
-
Selector::CommaSequence.new(selectors)
|
101
|
-
end
|
102
|
-
|
103
|
-
def selector_string
|
104
|
-
sel = selector
|
105
|
-
return unless sel
|
106
|
-
sel.to_s
|
107
|
-
end
|
108
|
-
|
109
|
-
def selector
|
110
|
-
start_pos = source_position
|
111
|
-
# The combinator here allows the "> E" hack
|
112
|
-
val = combinator || simple_selector_sequence
|
113
|
-
return unless val
|
114
|
-
nl = str {ss}.include?("\n")
|
115
|
-
res = []
|
116
|
-
res << val
|
117
|
-
res << "\n" if nl
|
118
|
-
|
119
|
-
while (val = combinator || simple_selector_sequence)
|
120
|
-
res << val
|
121
|
-
res << "\n" if str {ss}.include?("\n")
|
122
|
-
end
|
123
|
-
seq = Selector::Sequence.new(res.compact)
|
124
|
-
|
125
|
-
if seq.members.any? {|sseq| sseq.is_a?(Selector::SimpleSequence) && sseq.subject?}
|
126
|
-
location = " of #{@filename}" if @filename
|
127
|
-
Sass::Util.sass_warn <<MESSAGE
|
128
|
-
DEPRECATION WARNING on line #{start_pos.line}, column #{start_pos.offset}#{location}:
|
129
|
-
The subject selector operator "!" is deprecated and will be removed in a future release.
|
130
|
-
This operator has been replaced by ":has()" in the CSS spec.
|
131
|
-
For example: #{seq.subjectless}
|
132
|
-
MESSAGE
|
133
|
-
end
|
134
|
-
|
135
|
-
seq
|
136
|
-
end
|
137
|
-
|
138
|
-
def combinator
|
139
|
-
tok(PLUS) || tok(GREATER) || tok(TILDE) || reference_combinator
|
140
|
-
end
|
141
|
-
|
142
|
-
def reference_combinator
|
143
|
-
return unless tok(/\//)
|
144
|
-
res = '/'
|
145
|
-
ns, name = expr!(:qualified_name)
|
146
|
-
res << ns << '|' if ns
|
147
|
-
res << name << tok!(/\//)
|
148
|
-
res
|
149
|
-
end
|
150
|
-
|
151
|
-
def simple_selector_sequence
|
152
|
-
start_pos = source_position
|
153
|
-
e = element_name || id_selector || class_selector || placeholder_selector || attrib ||
|
154
|
-
pseudo || parent_selector
|
155
|
-
return unless e
|
156
|
-
res = [e]
|
157
|
-
|
158
|
-
# The tok(/\*/) allows the "E*" hack
|
159
|
-
while (v = id_selector || class_selector || placeholder_selector ||
|
160
|
-
attrib || pseudo || (tok(/\*/) && Selector::Universal.new(nil)))
|
161
|
-
res << v
|
162
|
-
end
|
163
|
-
|
164
|
-
pos = @scanner.pos
|
165
|
-
line = @line
|
166
|
-
if (sel = str? {simple_selector_sequence})
|
167
|
-
@scanner.pos = pos
|
168
|
-
@line = line
|
169
|
-
begin
|
170
|
-
# If we see "*E", don't force a throw because this could be the
|
171
|
-
# "*prop: val" hack.
|
172
|
-
expected('"{"') if res.length == 1 && res[0].is_a?(Selector::Universal)
|
173
|
-
throw_error {expected('"{"')}
|
174
|
-
rescue Sass::SyntaxError => e
|
175
|
-
e.message << "\n\n\"#{sel}\" may only be used at the beginning of a compound selector."
|
176
|
-
raise e
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
Selector::SimpleSequence.new(res, tok(/!/), range(start_pos))
|
181
|
-
end
|
182
|
-
|
183
|
-
def parent_selector
|
184
|
-
return unless @allow_parent_ref && tok(/&/)
|
185
|
-
Selector::Parent.new(tok(NAME))
|
186
|
-
end
|
187
|
-
|
188
|
-
def class_selector
|
189
|
-
return unless tok(/\./)
|
190
|
-
@expected = "class name"
|
191
|
-
Selector::Class.new(tok!(IDENT))
|
192
|
-
end
|
193
|
-
|
194
|
-
def id_selector
|
195
|
-
return unless tok(/#(?!\{)/)
|
196
|
-
@expected = "id name"
|
197
|
-
Selector::Id.new(tok!(NAME))
|
198
|
-
end
|
199
|
-
|
200
|
-
def placeholder_selector
|
201
|
-
return unless tok(/%/)
|
202
|
-
@expected = "placeholder name"
|
203
|
-
Selector::Placeholder.new(tok!(IDENT))
|
204
|
-
end
|
205
|
-
|
206
|
-
def element_name
|
207
|
-
ns, name = Sass::Util.destructure(qualified_name(:allow_star_name))
|
208
|
-
return unless ns || name
|
209
|
-
|
210
|
-
if name == '*'
|
211
|
-
Selector::Universal.new(ns)
|
212
|
-
else
|
213
|
-
Selector::Element.new(name, ns)
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
def qualified_name(allow_star_name = false)
|
218
|
-
name = tok(IDENT) || tok(/\*/) || (tok?(/\|/) && "")
|
219
|
-
return unless name
|
220
|
-
return nil, name unless tok(/\|/)
|
221
|
-
|
222
|
-
return name, tok!(IDENT) unless allow_star_name
|
223
|
-
@expected = "identifier or *"
|
224
|
-
return name, tok(IDENT) || tok!(/\*/)
|
225
|
-
end
|
226
|
-
|
227
|
-
def attrib
|
228
|
-
return unless tok(/\[/)
|
229
|
-
ss
|
230
|
-
ns, name = attrib_name!
|
231
|
-
ss
|
232
|
-
|
233
|
-
op = tok(/=/) ||
|
234
|
-
tok(INCLUDES) ||
|
235
|
-
tok(DASHMATCH) ||
|
236
|
-
tok(PREFIXMATCH) ||
|
237
|
-
tok(SUFFIXMATCH) ||
|
238
|
-
tok(SUBSTRINGMATCH)
|
239
|
-
if op
|
240
|
-
@expected = "identifier or string"
|
241
|
-
ss
|
242
|
-
val = tok(IDENT) || tok!(STRING)
|
243
|
-
ss
|
244
|
-
end
|
245
|
-
flags = tok(IDENT) || tok(STRING)
|
246
|
-
tok!(/\]/)
|
247
|
-
|
248
|
-
Selector::Attribute.new(name, ns, op, val, flags)
|
249
|
-
end
|
250
|
-
|
251
|
-
def attrib_name!
|
252
|
-
if (name_or_ns = tok(IDENT))
|
253
|
-
# E, E|E
|
254
|
-
if tok(/\|(?!=)/)
|
255
|
-
ns = name_or_ns
|
256
|
-
name = tok(IDENT)
|
257
|
-
else
|
258
|
-
name = name_or_ns
|
259
|
-
end
|
260
|
-
else
|
261
|
-
# *|E or |E
|
262
|
-
ns = tok(/\*/) || ""
|
263
|
-
tok!(/\|/)
|
264
|
-
name = tok!(IDENT)
|
265
|
-
end
|
266
|
-
return ns, name
|
267
|
-
end
|
268
|
-
|
269
|
-
SELECTOR_PSEUDO_CLASSES = %w[not matches current any has host host-context].to_set
|
270
|
-
|
271
|
-
PREFIXED_SELECTOR_PSEUDO_CLASSES = %w[nth-child nth-last-child].to_set
|
272
|
-
|
273
|
-
def pseudo
|
274
|
-
s = tok(/::?/)
|
275
|
-
return unless s
|
276
|
-
@expected = "pseudoclass or pseudoelement"
|
277
|
-
name = tok!(IDENT)
|
278
|
-
if tok(/\(/)
|
279
|
-
ss
|
280
|
-
deprefixed = deprefix(name)
|
281
|
-
if s == ':' && SELECTOR_PSEUDO_CLASSES.include?(deprefixed)
|
282
|
-
sel = selector_comma_sequence
|
283
|
-
elsif s == ':' && PREFIXED_SELECTOR_PSEUDO_CLASSES.include?(deprefixed)
|
284
|
-
arg, sel = prefixed_selector_pseudo
|
285
|
-
else
|
286
|
-
arg = expr!(:pseudo_args)
|
287
|
-
end
|
288
|
-
|
289
|
-
tok!(/\)/)
|
290
|
-
end
|
291
|
-
Selector::Pseudo.new(s == ':' ? :class : :element, name, arg, sel)
|
292
|
-
end
|
293
|
-
|
294
|
-
def pseudo_args
|
295
|
-
arg = expr!(:pseudo_expr)
|
296
|
-
while tok(/,/)
|
297
|
-
arg << ',' << str {ss}
|
298
|
-
arg.concat expr!(:pseudo_expr)
|
299
|
-
end
|
300
|
-
arg
|
301
|
-
end
|
302
|
-
|
303
|
-
def pseudo_expr
|
304
|
-
res = pseudo_expr_token
|
305
|
-
return unless res
|
306
|
-
res << str {ss}
|
307
|
-
while (e = pseudo_expr_token)
|
308
|
-
res << e << str {ss}
|
309
|
-
end
|
310
|
-
res
|
311
|
-
end
|
312
|
-
|
313
|
-
def pseudo_expr_token
|
314
|
-
tok(PLUS) || tok(/[-*]/) || tok(NUMBER) || tok(STRING) || tok(IDENT)
|
315
|
-
end
|
316
|
-
|
317
|
-
def prefixed_selector_pseudo
|
318
|
-
prefix = str do
|
319
|
-
expr = str {expr!(:a_n_plus_b)}
|
320
|
-
ss
|
321
|
-
return expr, nil unless tok(/of/)
|
322
|
-
ss
|
323
|
-
end
|
324
|
-
return prefix, expr!(:selector_comma_sequence)
|
325
|
-
end
|
326
|
-
|
327
|
-
def a_n_plus_b
|
328
|
-
if (parity = tok(/even|odd/i))
|
329
|
-
return parity
|
330
|
-
end
|
331
|
-
|
332
|
-
if tok(/[+-]?[0-9]+/)
|
333
|
-
ss
|
334
|
-
return true unless tok(/n/)
|
335
|
-
else
|
336
|
-
return unless tok(/[+-]?n/i)
|
337
|
-
end
|
338
|
-
ss
|
339
|
-
|
340
|
-
return true unless tok(/[+-]/)
|
341
|
-
ss
|
342
|
-
@expected = "number"
|
343
|
-
tok!(/[0-9]+/)
|
344
|
-
true
|
345
|
-
end
|
346
|
-
|
347
|
-
def keyframes_selector
|
348
|
-
ss
|
349
|
-
str do
|
350
|
-
return unless keyframes_selector_component
|
351
|
-
ss
|
352
|
-
while tok(/,/)
|
353
|
-
ss
|
354
|
-
expr!(:keyframes_selector_component)
|
355
|
-
ss
|
356
|
-
end
|
357
|
-
end
|
358
|
-
end
|
359
|
-
|
360
|
-
def keyframes_selector_component
|
361
|
-
tok(/from|to/i) || tok(PERCENTAGE)
|
362
|
-
end
|
363
|
-
|
364
50
|
@sass_script_parser = Class.new(Sass::Script::CssParser)
|
365
51
|
@sass_script_parser.send(:include, ScriptParser)
|
366
52
|
end
|
data/lib/sass/selector.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
require 'sass/selector/simple'
|
2
2
|
require 'sass/selector/abstract_sequence'
|
3
3
|
require 'sass/selector/comma_sequence'
|
4
|
-
require 'sass/selector/pseudo'
|
5
4
|
require 'sass/selector/sequence'
|
6
5
|
require 'sass/selector/simple_sequence'
|
7
6
|
|
8
7
|
module Sass
|
9
8
|
# A namespace for nodes in the parse tree for selectors.
|
10
9
|
#
|
11
|
-
# {CommaSequence} is the toplevel
|
10
|
+
# {CommaSequence} is the toplevel seelctor,
|
12
11
|
# representing a comma-separated sequence of {Sequence}s,
|
13
12
|
# such as `foo bar, baz bang`.
|
14
13
|
# {Sequence} is the next level,
|
@@ -22,25 +21,17 @@ module Sass
|
|
22
21
|
# The base used for calculating selector specificity. The spec says this
|
23
22
|
# should be "sufficiently high"; it's extremely unlikely that any single
|
24
23
|
# selector sequence will contain 1,000 simple selectors.
|
24
|
+
#
|
25
|
+
# @type [Fixnum]
|
25
26
|
SPECIFICITY_BASE = 1_000
|
26
27
|
|
27
28
|
# A parent-referencing selector (`&` in Sass).
|
28
29
|
# The function of this is to be replaced by the parent selector
|
29
30
|
# in the nested hierarchy.
|
30
31
|
class Parent < Simple
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
attr_reader :suffix
|
35
|
-
|
36
|
-
# @param name [String, nil] See \{#suffix}
|
37
|
-
def initialize(suffix = nil)
|
38
|
-
@suffix = suffix
|
39
|
-
end
|
40
|
-
|
41
|
-
# @see Selector#to_s
|
42
|
-
def to_s
|
43
|
-
"&" + (@suffix || '')
|
32
|
+
# @see Selector#to_a
|
33
|
+
def to_a
|
34
|
+
["&"]
|
44
35
|
end
|
45
36
|
|
46
37
|
# Always raises an exception.
|
@@ -56,17 +47,17 @@ module Sass
|
|
56
47
|
class Class < Simple
|
57
48
|
# The class name.
|
58
49
|
#
|
59
|
-
# @return [String]
|
50
|
+
# @return [Array<String, Sass::Script::Node>]
|
60
51
|
attr_reader :name
|
61
52
|
|
62
|
-
# @param name [String] The class name
|
53
|
+
# @param name [Array<String, Sass::Script::Node>] The class name
|
63
54
|
def initialize(name)
|
64
55
|
@name = name
|
65
56
|
end
|
66
57
|
|
67
|
-
# @see Selector#
|
68
|
-
def
|
69
|
-
"."
|
58
|
+
# @see Selector#to_a
|
59
|
+
def to_a
|
60
|
+
[".", *@name]
|
70
61
|
end
|
71
62
|
|
72
63
|
# @see AbstractSequence#specificity
|
@@ -79,17 +70,17 @@ module Sass
|
|
79
70
|
class Id < Simple
|
80
71
|
# The id name.
|
81
72
|
#
|
82
|
-
# @return [String]
|
73
|
+
# @return [Array<String, Sass::Script::Node>]
|
83
74
|
attr_reader :name
|
84
75
|
|
85
|
-
# @param name [String] The id name
|
76
|
+
# @param name [Array<String, Sass::Script::Node>] The id name
|
86
77
|
def initialize(name)
|
87
78
|
@name = name
|
88
79
|
end
|
89
80
|
|
90
|
-
# @see Selector#
|
91
|
-
def
|
92
|
-
"#"
|
81
|
+
# @see Selector#to_a
|
82
|
+
def to_a
|
83
|
+
["#", *@name]
|
93
84
|
end
|
94
85
|
|
95
86
|
# Returns `nil` if `sels` contains an {Id} selector
|
@@ -97,7 +88,7 @@ module Sass
|
|
97
88
|
#
|
98
89
|
# @see Selector#unify
|
99
90
|
def unify(sels)
|
100
|
-
return if sels.any? {|sel2| sel2.is_a?(Id) && name != sel2.name}
|
91
|
+
return if sels.any? {|sel2| sel2.is_a?(Id) && self.name != sel2.name}
|
101
92
|
super
|
102
93
|
end
|
103
94
|
|
@@ -114,17 +105,17 @@ module Sass
|
|
114
105
|
class Placeholder < Simple
|
115
106
|
# The placeholder name.
|
116
107
|
#
|
117
|
-
# @return [String]
|
108
|
+
# @return [Array<String, Sass::Script::Node>]
|
118
109
|
attr_reader :name
|
119
110
|
|
120
|
-
# @param name [String] The placeholder name
|
111
|
+
# @param name [Array<String, Sass::Script::Node>] The placeholder name
|
121
112
|
def initialize(name)
|
122
113
|
@name = name
|
123
114
|
end
|
124
115
|
|
125
|
-
# @see Selector#
|
126
|
-
def
|
127
|
-
"%"
|
116
|
+
# @see Selector#to_a
|
117
|
+
def to_a
|
118
|
+
["%", *@name]
|
128
119
|
end
|
129
120
|
|
130
121
|
# @see AbstractSequence#specificity
|
@@ -135,20 +126,22 @@ module Sass
|
|
135
126
|
|
136
127
|
# A universal selector (`*` in CSS).
|
137
128
|
class Universal < Simple
|
138
|
-
# The selector namespace.
|
139
|
-
#
|
129
|
+
# The selector namespace.
|
130
|
+
# `nil` means the default namespace,
|
131
|
+
# `[""]` means no namespace,
|
132
|
+
# `["*"]` means any namespace.
|
140
133
|
#
|
141
|
-
# @return [String, nil]
|
134
|
+
# @return [Array<String, Sass::Script::Node>, nil]
|
142
135
|
attr_reader :namespace
|
143
136
|
|
144
|
-
# @param namespace [String, nil] See \{#namespace}
|
137
|
+
# @param namespace [Array<String, Sass::Script::Node>, nil] See \{#namespace}
|
145
138
|
def initialize(namespace)
|
146
139
|
@namespace = namespace
|
147
140
|
end
|
148
141
|
|
149
|
-
# @see Selector#
|
150
|
-
def
|
151
|
-
@namespace ?
|
142
|
+
# @see Selector#to_a
|
143
|
+
def to_a
|
144
|
+
@namespace ? @namespace + ["|*"] : ["*"]
|
152
145
|
end
|
153
146
|
|
154
147
|
# Unification of a universal selector is somewhat complicated,
|
@@ -182,7 +175,7 @@ module Sass
|
|
182
175
|
when Universal; :universal
|
183
176
|
when Element; sels.first.name
|
184
177
|
else
|
185
|
-
return [self] + sels unless namespace.nil? || namespace == '*'
|
178
|
+
return [self] + sels unless namespace.nil? || namespace == ['*']
|
186
179
|
return sels unless sels.empty?
|
187
180
|
return [self]
|
188
181
|
end
|
@@ -202,25 +195,27 @@ module Sass
|
|
202
195
|
class Element < Simple
|
203
196
|
# The element name.
|
204
197
|
#
|
205
|
-
# @return [String]
|
198
|
+
# @return [Array<String, Sass::Script::Node>]
|
206
199
|
attr_reader :name
|
207
200
|
|
208
|
-
# The selector namespace.
|
209
|
-
#
|
201
|
+
# The selector namespace.
|
202
|
+
# `nil` means the default namespace,
|
203
|
+
# `[""]` means no namespace,
|
204
|
+
# `["*"]` means any namespace.
|
210
205
|
#
|
211
|
-
# @return [String, nil]
|
206
|
+
# @return [Array<String, Sass::Script::Node>, nil]
|
212
207
|
attr_reader :namespace
|
213
208
|
|
214
|
-
# @param name [String] The element name
|
215
|
-
# @param namespace [String, nil] See \{#namespace}
|
209
|
+
# @param name [Array<String, Sass::Script::Node>] The element name
|
210
|
+
# @param namespace [Array<String, Sass::Script::Node>, nil] See \{#namespace}
|
216
211
|
def initialize(name, namespace)
|
217
212
|
@name = name
|
218
213
|
@namespace = namespace
|
219
214
|
end
|
220
215
|
|
221
|
-
# @see Selector#
|
222
|
-
def
|
223
|
-
@namespace ?
|
216
|
+
# @see Selector#to_a
|
217
|
+
def to_a
|
218
|
+
@namespace ? @namespace + ["|"] + @name : @name
|
224
219
|
end
|
225
220
|
|
226
221
|
# Unification of an element selector is somewhat complicated,
|
@@ -263,17 +258,45 @@ module Sass
|
|
263
258
|
end
|
264
259
|
end
|
265
260
|
|
261
|
+
# Selector interpolation (`#{}` in Sass).
|
262
|
+
class Interpolation < Simple
|
263
|
+
# The script to run.
|
264
|
+
#
|
265
|
+
# @return [Sass::Script::Node]
|
266
|
+
attr_reader :script
|
267
|
+
|
268
|
+
# @param script [Sass::Script::Node] The script to run
|
269
|
+
def initialize(script)
|
270
|
+
@script = script
|
271
|
+
end
|
272
|
+
|
273
|
+
# @see Selector#to_a
|
274
|
+
def to_a
|
275
|
+
[@script]
|
276
|
+
end
|
277
|
+
|
278
|
+
# Always raises an exception.
|
279
|
+
#
|
280
|
+
# @raise [Sass::SyntaxError] Interpolation selectors should be resolved before unification
|
281
|
+
# @see Selector#unify
|
282
|
+
def unify(sels)
|
283
|
+
raise Sass::SyntaxError.new("[BUG] Cannot unify interpolation selectors.")
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
266
287
|
# An attribute selector (e.g. `[href^="http://"]`).
|
267
288
|
class Attribute < Simple
|
268
289
|
# The attribute name.
|
269
290
|
#
|
270
|
-
# @return [Array<String, Sass::Script::
|
291
|
+
# @return [Array<String, Sass::Script::Node>]
|
271
292
|
attr_reader :name
|
272
293
|
|
273
|
-
# The attribute namespace.
|
274
|
-
#
|
294
|
+
# The attribute namespace.
|
295
|
+
# `nil` means the default namespace,
|
296
|
+
# `[""]` means no namespace,
|
297
|
+
# `["*"]` means any namespace.
|
275
298
|
#
|
276
|
-
# @return [String, nil]
|
299
|
+
# @return [Array<String, Sass::Script::Node>, nil]
|
277
300
|
attr_reader :namespace
|
278
301
|
|
279
302
|
# The matching operator, e.g. `"="` or `"^="`.
|
@@ -283,23 +306,20 @@ module Sass
|
|
283
306
|
|
284
307
|
# The right-hand side of the operator.
|
285
308
|
#
|
286
|
-
# @return [String]
|
309
|
+
# @return [Array<String, Sass::Script::Node>]
|
287
310
|
attr_reader :value
|
288
311
|
|
289
312
|
# Flags for the attribute selector (e.g. `i`).
|
290
313
|
#
|
291
|
-
# @return [String]
|
314
|
+
# @return [Array<String, Sass::Script::Node>]
|
292
315
|
attr_reader :flags
|
293
316
|
|
294
|
-
# @param name [String] The attribute name
|
295
|
-
# @param namespace [String, nil] See \{#namespace}
|
317
|
+
# @param name [Array<String, Sass::Script::Node>] The attribute name
|
318
|
+
# @param namespace [Array<String, Sass::Script::Node>, nil] See \{#namespace}
|
296
319
|
# @param operator [String] The matching operator, e.g. `"="` or `"^="`
|
297
|
-
# @param value [String] See \{#value}
|
298
|
-
# @param
|
299
|
-
# @comment
|
300
|
-
# rubocop:disable ParameterLists
|
320
|
+
# @param value [Array<String, Sass::Script::Node>] See \{#value}
|
321
|
+
# @param value [Array<String, Sass::Script::Node>] See \{#flags}
|
301
322
|
def initialize(name, namespace, operator, value, flags)
|
302
|
-
# rubocop:enable ParameterLists
|
303
323
|
@name = name
|
304
324
|
@namespace = namespace
|
305
325
|
@operator = operator
|
@@ -307,13 +327,13 @@ module Sass
|
|
307
327
|
@flags = flags
|
308
328
|
end
|
309
329
|
|
310
|
-
# @see Selector#
|
311
|
-
def
|
312
|
-
res = "["
|
313
|
-
res
|
314
|
-
res
|
315
|
-
res << @operator
|
316
|
-
res << " "
|
330
|
+
# @see Selector#to_a
|
331
|
+
def to_a
|
332
|
+
res = ["["]
|
333
|
+
res.concat(@namespace) << "|" if @namespace
|
334
|
+
res.concat @name
|
335
|
+
(res << @operator).concat @value if @value
|
336
|
+
(res << " ").concat @flags if @flags
|
317
337
|
res << "]"
|
318
338
|
end
|
319
339
|
|
@@ -322,5 +342,111 @@ module Sass
|
|
322
342
|
SPECIFICITY_BASE
|
323
343
|
end
|
324
344
|
end
|
345
|
+
|
346
|
+
# A pseudoclass (e.g. `:visited`) or pseudoelement (e.g. `::first-line`) selector.
|
347
|
+
# It can have arguments (e.g. `:nth-child(2n+1)`).
|
348
|
+
class Pseudo < Simple
|
349
|
+
# Some psuedo-class-syntax selectors are actually considered
|
350
|
+
# pseudo-elements and must be treated differently. This is a list of such
|
351
|
+
# selectors
|
352
|
+
#
|
353
|
+
# @return [Array<String>]
|
354
|
+
ACTUALLY_ELEMENTS = %w[after before first-line first-letter]
|
355
|
+
|
356
|
+
# Like \{#type}, but returns the type of selector this looks like, rather
|
357
|
+
# than the type it is semantically. This only differs from type for
|
358
|
+
# selectors in \{ACTUALLY\_ELEMENTS}.
|
359
|
+
#
|
360
|
+
# @return [Symbol]
|
361
|
+
attr_reader :syntactic_type
|
362
|
+
|
363
|
+
# The name of the selector.
|
364
|
+
#
|
365
|
+
# @return [Array<String, Sass::Script::Node>]
|
366
|
+
attr_reader :name
|
367
|
+
|
368
|
+
# The argument to the selector,
|
369
|
+
# or `nil` if no argument was given.
|
370
|
+
#
|
371
|
+
# This may include SassScript nodes that will be run during resolution.
|
372
|
+
# Note that this should not include SassScript nodes
|
373
|
+
# after resolution has taken place.
|
374
|
+
#
|
375
|
+
# @return [Array<String, Sass::Script::Node>, nil]
|
376
|
+
attr_reader :arg
|
377
|
+
|
378
|
+
# @param type [Symbol] See \{#type}
|
379
|
+
# @param name [Array<String, Sass::Script::Node>] The name of the selector
|
380
|
+
# @param arg [nil, Array<String, Sass::Script::Node>] The argument to the selector,
|
381
|
+
# or nil if no argument was given
|
382
|
+
def initialize(type, name, arg)
|
383
|
+
@syntactic_type = type
|
384
|
+
@name = name
|
385
|
+
@arg = arg
|
386
|
+
end
|
387
|
+
|
388
|
+
# The type of the selector. `:class` if this is a pseudoclass selector,
|
389
|
+
# `:element` if it's a pseudoelement.
|
390
|
+
#
|
391
|
+
# @return [Symbol]
|
392
|
+
def type
|
393
|
+
ACTUALLY_ELEMENTS.include?(name.first) ? :element : syntactic_type
|
394
|
+
end
|
395
|
+
|
396
|
+
# @see Selector#to_a
|
397
|
+
def to_a
|
398
|
+
res = [syntactic_type == :class ? ":" : "::"] + @name
|
399
|
+
(res << "(").concat(Sass::Util.strip_string_array(@arg)) << ")" if @arg
|
400
|
+
res
|
401
|
+
end
|
402
|
+
|
403
|
+
# Returns `nil` if this is a pseudoelement selector
|
404
|
+
# and `sels` contains a pseudoelement selector different than this one.
|
405
|
+
#
|
406
|
+
# @see Selector#unify
|
407
|
+
def unify(sels)
|
408
|
+
return if type == :element && sels.any? do |sel|
|
409
|
+
sel.is_a?(Pseudo) && sel.type == :element &&
|
410
|
+
(sel.name != self.name || sel.arg != self.arg)
|
411
|
+
end
|
412
|
+
super
|
413
|
+
end
|
414
|
+
|
415
|
+
# @see AbstractSequence#specificity
|
416
|
+
def specificity
|
417
|
+
type == :class ? SPECIFICITY_BASE : 1
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
# A pseudoclass selector whose argument is itself a selector
|
422
|
+
# (e.g. `:not(.foo)` or `:-moz-all(.foo, .bar)`).
|
423
|
+
class SelectorPseudoClass < Simple
|
424
|
+
# The name of the pseudoclass.
|
425
|
+
#
|
426
|
+
# @return [String]
|
427
|
+
attr_reader :name
|
428
|
+
|
429
|
+
# The selector argument.
|
430
|
+
#
|
431
|
+
# @return [Selector::Sequence]
|
432
|
+
attr_reader :selector
|
433
|
+
|
434
|
+
# @param [String] The name of the pseudoclass
|
435
|
+
# @param [Selector::CommaSequence] The selector argument
|
436
|
+
def initialize(name, selector)
|
437
|
+
@name = name
|
438
|
+
@selector = selector
|
439
|
+
end
|
440
|
+
|
441
|
+
# @see Selector#to_a
|
442
|
+
def to_a
|
443
|
+
[":", @name, "("] + @selector.to_a + [")"]
|
444
|
+
end
|
445
|
+
|
446
|
+
# @see AbstractSequence#specificity
|
447
|
+
def specificity
|
448
|
+
SPECIFICITY_BASE
|
449
|
+
end
|
450
|
+
end
|
325
451
|
end
|
326
452
|
end
|