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.
Files changed (147) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +13 -0
  3. data/AGENTS.md +534 -0
  4. data/CODE_OF_CONDUCT.md +10 -0
  5. data/CONTRIBUTING.md +148 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +242 -0
  8. data/VERSION +1 -0
  9. data/VERSION_NAME +1 -0
  10. data/bin/sass +13 -0
  11. data/bin/sass-convert +12 -0
  12. data/bin/scss +13 -0
  13. data/extra/sass-spec-ref.sh +40 -0
  14. data/extra/update_watch.rb +13 -0
  15. data/init.rb +18 -0
  16. data/lib/sass/cache_stores/base.rb +88 -0
  17. data/lib/sass/cache_stores/chain.rb +34 -0
  18. data/lib/sass/cache_stores/filesystem.rb +60 -0
  19. data/lib/sass/cache_stores/memory.rb +46 -0
  20. data/lib/sass/cache_stores/null.rb +25 -0
  21. data/lib/sass/cache_stores.rb +15 -0
  22. data/lib/sass/callbacks.rb +67 -0
  23. data/lib/sass/css.rb +407 -0
  24. data/lib/sass/deprecation.rb +55 -0
  25. data/lib/sass/engine.rb +1236 -0
  26. data/lib/sass/environment.rb +236 -0
  27. data/lib/sass/error.rb +198 -0
  28. data/lib/sass/exec/base.rb +188 -0
  29. data/lib/sass/exec/sass_convert.rb +283 -0
  30. data/lib/sass/exec/sass_scss.rb +436 -0
  31. data/lib/sass/exec.rb +9 -0
  32. data/lib/sass/features.rb +48 -0
  33. data/lib/sass/importers/base.rb +182 -0
  34. data/lib/sass/importers/deprecated_path.rb +51 -0
  35. data/lib/sass/importers/filesystem.rb +221 -0
  36. data/lib/sass/importers.rb +23 -0
  37. data/lib/sass/logger/base.rb +47 -0
  38. data/lib/sass/logger/delayed.rb +50 -0
  39. data/lib/sass/logger/log_level.rb +45 -0
  40. data/lib/sass/logger.rb +17 -0
  41. data/lib/sass/media.rb +210 -0
  42. data/lib/sass/plugin/compiler.rb +552 -0
  43. data/lib/sass/plugin/configuration.rb +134 -0
  44. data/lib/sass/plugin/generic.rb +15 -0
  45. data/lib/sass/plugin/merb.rb +48 -0
  46. data/lib/sass/plugin/rack.rb +60 -0
  47. data/lib/sass/plugin/rails.rb +47 -0
  48. data/lib/sass/plugin/staleness_checker.rb +199 -0
  49. data/lib/sass/plugin.rb +134 -0
  50. data/lib/sass/railtie.rb +10 -0
  51. data/lib/sass/repl.rb +57 -0
  52. data/lib/sass/root.rb +7 -0
  53. data/lib/sass/script/css_lexer.rb +33 -0
  54. data/lib/sass/script/css_parser.rb +36 -0
  55. data/lib/sass/script/functions.rb +3103 -0
  56. data/lib/sass/script/lexer.rb +518 -0
  57. data/lib/sass/script/parser.rb +1164 -0
  58. data/lib/sass/script/tree/funcall.rb +314 -0
  59. data/lib/sass/script/tree/interpolation.rb +220 -0
  60. data/lib/sass/script/tree/list_literal.rb +119 -0
  61. data/lib/sass/script/tree/literal.rb +49 -0
  62. data/lib/sass/script/tree/map_literal.rb +64 -0
  63. data/lib/sass/script/tree/node.rb +119 -0
  64. data/lib/sass/script/tree/operation.rb +149 -0
  65. data/lib/sass/script/tree/selector.rb +26 -0
  66. data/lib/sass/script/tree/string_interpolation.rb +125 -0
  67. data/lib/sass/script/tree/unary_operation.rb +69 -0
  68. data/lib/sass/script/tree/variable.rb +57 -0
  69. data/lib/sass/script/tree.rb +16 -0
  70. data/lib/sass/script/value/arg_list.rb +36 -0
  71. data/lib/sass/script/value/base.rb +258 -0
  72. data/lib/sass/script/value/bool.rb +35 -0
  73. data/lib/sass/script/value/callable.rb +25 -0
  74. data/lib/sass/script/value/color.rb +704 -0
  75. data/lib/sass/script/value/function.rb +19 -0
  76. data/lib/sass/script/value/helpers.rb +298 -0
  77. data/lib/sass/script/value/list.rb +135 -0
  78. data/lib/sass/script/value/map.rb +70 -0
  79. data/lib/sass/script/value/null.rb +44 -0
  80. data/lib/sass/script/value/number.rb +564 -0
  81. data/lib/sass/script/value/string.rb +138 -0
  82. data/lib/sass/script/value.rb +13 -0
  83. data/lib/sass/script.rb +66 -0
  84. data/lib/sass/scss/css_parser.rb +61 -0
  85. data/lib/sass/scss/parser.rb +1343 -0
  86. data/lib/sass/scss/rx.rb +134 -0
  87. data/lib/sass/scss/static_parser.rb +351 -0
  88. data/lib/sass/scss.rb +14 -0
  89. data/lib/sass/selector/abstract_sequence.rb +112 -0
  90. data/lib/sass/selector/comma_sequence.rb +195 -0
  91. data/lib/sass/selector/pseudo.rb +291 -0
  92. data/lib/sass/selector/sequence.rb +661 -0
  93. data/lib/sass/selector/simple.rb +124 -0
  94. data/lib/sass/selector/simple_sequence.rb +348 -0
  95. data/lib/sass/selector.rb +327 -0
  96. data/lib/sass/shared.rb +76 -0
  97. data/lib/sass/source/map.rb +209 -0
  98. data/lib/sass/source/position.rb +39 -0
  99. data/lib/sass/source/range.rb +41 -0
  100. data/lib/sass/stack.rb +140 -0
  101. data/lib/sass/supports.rb +225 -0
  102. data/lib/sass/tree/at_root_node.rb +83 -0
  103. data/lib/sass/tree/charset_node.rb +22 -0
  104. data/lib/sass/tree/comment_node.rb +82 -0
  105. data/lib/sass/tree/content_node.rb +9 -0
  106. data/lib/sass/tree/css_import_node.rb +68 -0
  107. data/lib/sass/tree/debug_node.rb +18 -0
  108. data/lib/sass/tree/directive_node.rb +59 -0
  109. data/lib/sass/tree/each_node.rb +24 -0
  110. data/lib/sass/tree/error_node.rb +18 -0
  111. data/lib/sass/tree/extend_node.rb +43 -0
  112. data/lib/sass/tree/for_node.rb +36 -0
  113. data/lib/sass/tree/function_node.rb +44 -0
  114. data/lib/sass/tree/if_node.rb +52 -0
  115. data/lib/sass/tree/import_node.rb +75 -0
  116. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  117. data/lib/sass/tree/media_node.rb +48 -0
  118. data/lib/sass/tree/mixin_def_node.rb +38 -0
  119. data/lib/sass/tree/mixin_node.rb +52 -0
  120. data/lib/sass/tree/node.rb +240 -0
  121. data/lib/sass/tree/prop_node.rb +162 -0
  122. data/lib/sass/tree/return_node.rb +19 -0
  123. data/lib/sass/tree/root_node.rb +44 -0
  124. data/lib/sass/tree/rule_node.rb +153 -0
  125. data/lib/sass/tree/supports_node.rb +38 -0
  126. data/lib/sass/tree/trace_node.rb +33 -0
  127. data/lib/sass/tree/variable_node.rb +36 -0
  128. data/lib/sass/tree/visitors/base.rb +72 -0
  129. data/lib/sass/tree/visitors/check_nesting.rb +173 -0
  130. data/lib/sass/tree/visitors/convert.rb +350 -0
  131. data/lib/sass/tree/visitors/cssize.rb +362 -0
  132. data/lib/sass/tree/visitors/deep_copy.rb +107 -0
  133. data/lib/sass/tree/visitors/extend.rb +64 -0
  134. data/lib/sass/tree/visitors/perform.rb +572 -0
  135. data/lib/sass/tree/visitors/set_options.rb +139 -0
  136. data/lib/sass/tree/visitors/to_css.rb +440 -0
  137. data/lib/sass/tree/warn_node.rb +18 -0
  138. data/lib/sass/tree/while_node.rb +18 -0
  139. data/lib/sass/util/multibyte_string_scanner.rb +151 -0
  140. data/lib/sass/util/normalized_map.rb +122 -0
  141. data/lib/sass/util/subset_map.rb +109 -0
  142. data/lib/sass/util/test.rb +9 -0
  143. data/lib/sass/util.rb +1137 -0
  144. data/lib/sass/version.rb +120 -0
  145. data/lib/sass.rb +102 -0
  146. data/rails/init.rb +1 -0
  147. metadata +283 -0
@@ -0,0 +1,134 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Sass
3
+ module SCSS
4
+ # A module containing regular expressions used
5
+ # for lexing tokens in an SCSS document.
6
+ # Most of these are taken from [the CSS3 spec](http://www.w3.org/TR/css3-syntax/#lexical),
7
+ # although some have been modified for various reasons.
8
+ module RX
9
+ # Takes a string and returns a CSS identifier
10
+ # that will have the value of the given string.
11
+ #
12
+ # @param str [String] The string to escape
13
+ # @return [String] The escaped string
14
+ def self.escape_ident(str)
15
+ return "" if str.empty?
16
+ return "\\#{str}" if str == '-' || str == '_'
17
+ out = ""
18
+ value = str.dup
19
+ out << value.slice!(0...1) if value =~ /^[-_]/
20
+ if value[0...1] =~ NMSTART
21
+ out << value.slice!(0...1)
22
+ else
23
+ out << escape_char(value.slice!(0...1))
24
+ end
25
+ out << value.gsub(/[^a-zA-Z0-9_-]/) {|c| escape_char c}
26
+ out
27
+ end
28
+
29
+ # Escapes a single character for a CSS identifier.
30
+ #
31
+ # @param c [String] The character to escape. Should have length 1
32
+ # @return [String] The escaped character
33
+ # @private
34
+ def self.escape_char(c)
35
+ return "\\%06x" % c.ord unless c =~ %r{[ -/:-~]}
36
+ "\\#{c}"
37
+ end
38
+
39
+ # Creates a Regexp from a plain text string,
40
+ # escaping all significant characters.
41
+ #
42
+ # @param str [String] The text of the regexp
43
+ # @param flags [Integer] Flags for the created regular expression
44
+ # @return [Regexp]
45
+ # @private
46
+ def self.quote(str, flags = 0)
47
+ Regexp.new(Regexp.quote(str), flags)
48
+ end
49
+
50
+ H = /[0-9a-fA-F]/
51
+ NL = /\n|\r\n|\r|\f/
52
+ UNICODE = /\\#{H}{1,6}[ \t\r\n\f]?/
53
+ s = '\u{80}-\u{D7FF}\u{E000}-\u{FFFD}\u{10000}-\u{10FFFF}'
54
+ NONASCII = /[#{s}]/
55
+ ESCAPE = /#{UNICODE}|\\[^0-9a-fA-F\r\n\f]/
56
+ NMSTART = /[_a-zA-Z]|#{NONASCII}|#{ESCAPE}/
57
+ NMCHAR = /[a-zA-Z0-9_-]|#{NONASCII}|#{ESCAPE}/
58
+ STRING1 = /\"((?:[^\n\r\f\\"]|\\#{NL}|#{ESCAPE})*)\"/
59
+ STRING2 = /\'((?:[^\n\r\f\\']|\\#{NL}|#{ESCAPE})*)\'/
60
+
61
+ IDENT = /-*#{NMSTART}#{NMCHAR}*/
62
+ NAME = /#{NMCHAR}+/
63
+ STRING = /#{STRING1}|#{STRING2}/
64
+ URLCHAR = /[#%&*-~]|#{NONASCII}|#{ESCAPE}/
65
+ URL = /(#{URLCHAR}*)/
66
+ W = /[ \t\r\n\f]*/
67
+ VARIABLE = /(\$)(#{Sass::SCSS::RX::IDENT})/
68
+
69
+ # This is more liberal than the spec's definition,
70
+ # but that definition didn't work well with the greediness rules
71
+ RANGE = /(?:#{H}|\?){1,6}/
72
+
73
+ ##
74
+
75
+ S = /[ \t\r\n\f]+/
76
+
77
+ COMMENT = %r{/\*([^*]|\*+[^/*])*\**\*/}
78
+ SINGLE_LINE_COMMENT = %r{//.*(\n[ \t]*//.*)*}
79
+
80
+ CDO = quote("<!--")
81
+ CDC = quote("-->")
82
+ INCLUDES = quote("~=")
83
+ DASHMATCH = quote("|=")
84
+ PREFIXMATCH = quote("^=")
85
+ SUFFIXMATCH = quote("$=")
86
+ SUBSTRINGMATCH = quote("*=")
87
+
88
+ HASH = /##{NAME}/
89
+
90
+ IMPORTANT = /!#{W}important/i
91
+
92
+ # A unit is like an IDENT, but disallows a hyphen followed by a digit.
93
+ # This allows "1px-2px" to be interpreted as subtraction rather than "1"
94
+ # with the unit "px-2px". It also allows "%".
95
+ UNIT = /-?#{NMSTART}(?:[a-zA-Z0-9_]|#{NONASCII}|#{ESCAPE}|-(?!\.?\d))*|%/
96
+
97
+ UNITLESS_NUMBER = /(?:[0-9]+|[0-9]*\.[0-9]+)(?:[eE][+-]?\d+)?/
98
+ NUMBER = /#{UNITLESS_NUMBER}(?:#{UNIT})?/
99
+ PERCENTAGE = /#{UNITLESS_NUMBER}%/
100
+
101
+ URI = /url\(#{W}(?:#{STRING}|#{URL})#{W}\)/i
102
+ FUNCTION = /#{IDENT}\(/
103
+
104
+ UNICODERANGE = /u\+(?:#{H}{1,6}-#{H}{1,6}|#{RANGE})/i
105
+
106
+ # Defined in http://www.w3.org/TR/css3-selectors/#lex
107
+ PLUS = /#{W}\+/
108
+ GREATER = /#{W}>/
109
+ TILDE = /#{W}~/
110
+ NOT = quote(":not(", Regexp::IGNORECASE)
111
+
112
+ # Defined in https://developer.mozilla.org/en/CSS/@-moz-document as a
113
+ # non-standard version of http://www.w3.org/TR/css3-conditional/
114
+ URL_PREFIX = /url-prefix\(#{W}(?:#{STRING}|#{URL})#{W}\)/i
115
+ DOMAIN = /domain\(#{W}(?:#{STRING}|#{URL})#{W}\)/i
116
+
117
+ # Custom
118
+ HEXCOLOR = /\#[0-9a-fA-F]+/
119
+ INTERP_START = /#\{/
120
+ ANY = /:(-[-\w]+-)?any\(/i
121
+ OPTIONAL = /!#{W}optional/i
122
+ IDENT_START = /-|#{NMSTART}/
123
+
124
+ IDENT_HYPHEN_INTERP = /-+(?=#\{)/
125
+ STRING1_NOINTERP = /\"((?:[^\n\r\f\\"#]|#(?!\{)|#{ESCAPE})*)\"/
126
+ STRING2_NOINTERP = /\'((?:[^\n\r\f\\'#]|#(?!\{)|#{ESCAPE})*)\'/
127
+ STRING_NOINTERP = /#{STRING1_NOINTERP}|#{STRING2_NOINTERP}/
128
+
129
+ STATIC_COMPONENT = /#{IDENT}|#{STRING_NOINTERP}|#{HEXCOLOR}|[+-]?#{NUMBER}|\!important/i
130
+ STATIC_VALUE = %r(#{STATIC_COMPONENT}(\s*[\s,\/]\s*#{STATIC_COMPONENT})*(?=[;}]))i
131
+ STATIC_SELECTOR = /(#{NMCHAR}|[ \t]|[,>+*]|[:#.]#{NMSTART}){1,50}([{])/i
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,351 @@
1
+ require 'sass/script/css_parser'
2
+
3
+ module Sass
4
+ module SCSS
5
+ # A parser for a static SCSS tree.
6
+ # Parses with SCSS extensions, like nested rules and parent selectors,
7
+ # but without dynamic SassScript.
8
+ # This is useful for e.g. \{#parse\_selector parsing selectors}
9
+ # after resolving the interpolation.
10
+ class StaticParser < Parser
11
+ # Parses the text as a selector.
12
+ #
13
+ # @param filename [String, nil] The file in which the selector appears,
14
+ # or nil if there is no such file.
15
+ # Used for error reporting.
16
+ # @return [Selector::CommaSequence] The parsed selector
17
+ # @raise [Sass::SyntaxError] if there's a syntax error in the selector
18
+ def parse_selector
19
+ init_scanner!
20
+ seq = expr!(:selector_comma_sequence)
21
+ expected("selector") unless @scanner.eos?
22
+ seq.line = @line
23
+ seq.filename = @filename
24
+ seq
25
+ end
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
+ def initialize(str, filename, importer, line = 1, offset = 1, allow_parent_ref = true)
55
+ super(str, filename, importer, line, offset)
56
+ @allow_parent_ref = allow_parent_ref
57
+ end
58
+
59
+ private
60
+
61
+ def moz_document_function
62
+ val = tok(URI) || tok(URL_PREFIX) || tok(DOMAIN) || function(false)
63
+ return unless val
64
+ ss
65
+ [val]
66
+ end
67
+
68
+ def variable; nil; end
69
+ def script_value; nil; end
70
+ def interpolation(warn_for_color = false); nil; end
71
+ def var_expr; nil; end
72
+ def interp_string; (s = tok(STRING)) && [s]; end
73
+ def interp_uri; (s = tok(URI)) && [s]; end
74
+ def interp_ident; (s = ident) && [s]; end
75
+ def use_css_import?; true; end
76
+
77
+ def special_directive(name, start_pos)
78
+ return unless %w(media import charset -moz-document).include?(name)
79
+ super
80
+ end
81
+
82
+ def selector_comma_sequence
83
+ sel = selector
84
+ return unless sel
85
+ selectors = [sel]
86
+ ws = ''
87
+ while tok(/,/)
88
+ ws << str {ss}
89
+ next unless (sel = selector)
90
+ selectors << sel
91
+ if ws.include?("\n")
92
+ selectors[-1] = Selector::Sequence.new(["\n"] + selectors.last.members)
93
+ end
94
+ ws = ''
95
+ end
96
+ Selector::CommaSequence.new(selectors)
97
+ end
98
+
99
+ def selector_string
100
+ sel = selector
101
+ return unless sel
102
+ sel.to_s
103
+ end
104
+
105
+ def selector
106
+ start_pos = source_position
107
+ # The combinator here allows the "> E" hack
108
+ val = combinator || simple_selector_sequence
109
+ return unless val
110
+ nl = str {ss}.include?("\n")
111
+ res = []
112
+ res << val
113
+ res << "\n" if nl
114
+
115
+ while (val = combinator || simple_selector_sequence)
116
+ res << val
117
+ res << "\n" if str {ss}.include?("\n")
118
+ end
119
+ seq = Selector::Sequence.new(res.compact)
120
+
121
+ if seq.members.any? {|sseq| sseq.is_a?(Selector::SimpleSequence) && sseq.subject?}
122
+ location = " of #{@filename}" if @filename
123
+ Sass::Util.sass_warn <<MESSAGE
124
+ DEPRECATION WARNING on line #{start_pos.line}, column #{start_pos.offset}#{location}:
125
+ The subject selector operator "!" is deprecated and will be removed in a future release.
126
+ This operator has been replaced by ":has()" in the CSS spec.
127
+ For example: #{seq.subjectless}
128
+ MESSAGE
129
+ end
130
+
131
+ seq
132
+ end
133
+
134
+ def combinator
135
+ tok(PLUS) || tok(GREATER) || tok(TILDE) || reference_combinator
136
+ end
137
+
138
+ def reference_combinator
139
+ return unless tok(%r{/})
140
+ res = '/'
141
+ ns, name = expr!(:qualified_name)
142
+ res << ns << '|' if ns
143
+ res << name << tok!(%r{/})
144
+
145
+ location = " of #{@filename}" if @filename
146
+ Sass::Util.sass_warn <<MESSAGE
147
+ DEPRECATION WARNING on line #{@line}, column #{@offset}#{location}:
148
+ The reference combinator #{res} is deprecated and will be removed in a future release.
149
+ MESSAGE
150
+
151
+ res
152
+ end
153
+
154
+ def simple_selector_sequence
155
+ start_pos = source_position
156
+ e = element_name || id_selector || class_selector || placeholder_selector || attrib ||
157
+ pseudo || parent_selector
158
+ return unless e
159
+ res = [e]
160
+
161
+ # The tok(/\*/) allows the "E*" hack
162
+ while (v = id_selector || class_selector || placeholder_selector ||
163
+ attrib || pseudo || (tok(/\*/) && Selector::Universal.new(nil)))
164
+ res << v
165
+ end
166
+
167
+ pos = @scanner.pos
168
+ line = @line
169
+ if (sel = str? {simple_selector_sequence})
170
+ @scanner.pos = pos
171
+ @line = line
172
+ begin
173
+ # If we see "*E", don't force a throw because this could be the
174
+ # "*prop: val" hack.
175
+ expected('"{"') if res.length == 1 && res[0].is_a?(Selector::Universal)
176
+ throw_error {expected('"{"')}
177
+ rescue Sass::SyntaxError => e
178
+ e.message << "\n\n\"#{sel}\" may only be used at the beginning of a compound selector."
179
+ raise e
180
+ end
181
+ end
182
+
183
+ Selector::SimpleSequence.new(res, tok(/!/), range(start_pos))
184
+ end
185
+
186
+ def parent_selector
187
+ return unless @allow_parent_ref && tok(/&/)
188
+ Selector::Parent.new(name)
189
+ end
190
+
191
+ def class_selector
192
+ return unless tok(/\./)
193
+ @expected = "class name"
194
+ Selector::Class.new(ident!)
195
+ end
196
+
197
+ def id_selector
198
+ return unless tok(/#(?!\{)/)
199
+ @expected = "id name"
200
+ Selector::Id.new(name!)
201
+ end
202
+
203
+ def placeholder_selector
204
+ return unless tok(/%/)
205
+ @expected = "placeholder name"
206
+ Selector::Placeholder.new(ident!)
207
+ end
208
+
209
+ def element_name
210
+ ns, name = Sass::Util.destructure(qualified_name(:allow_star_name))
211
+ return unless ns || name
212
+
213
+ if name == '*'
214
+ Selector::Universal.new(ns)
215
+ else
216
+ Selector::Element.new(name, ns)
217
+ end
218
+ end
219
+
220
+ def qualified_name(allow_star_name = false)
221
+ name = ident || tok(/\*/) || (tok?(/\|/) && "")
222
+ return unless name
223
+ return nil, name unless tok(/\|/)
224
+
225
+ return name, ident! unless allow_star_name
226
+ @expected = "identifier or *"
227
+ return name, ident || tok!(/\*/)
228
+ end
229
+
230
+ def attrib
231
+ return unless tok(/\[/)
232
+ ss
233
+ ns, name = attrib_name!
234
+ ss
235
+
236
+ op = tok(/=/) ||
237
+ tok(INCLUDES) ||
238
+ tok(DASHMATCH) ||
239
+ tok(PREFIXMATCH) ||
240
+ tok(SUFFIXMATCH) ||
241
+ tok(SUBSTRINGMATCH)
242
+ if op
243
+ @expected = "identifier or string"
244
+ ss
245
+ val = ident || tok!(STRING)
246
+ ss
247
+ end
248
+ flags = ident || tok(STRING)
249
+ tok!(/\]/)
250
+
251
+ Selector::Attribute.new(name, ns, op, val, flags)
252
+ end
253
+
254
+ def attrib_name!
255
+ if (name_or_ns = ident)
256
+ # E, E|E
257
+ if tok(/\|(?!=)/)
258
+ ns = name_or_ns
259
+ name = ident
260
+ else
261
+ name = name_or_ns
262
+ end
263
+ else
264
+ # *|E or |E
265
+ ns = tok(/\*/) || ""
266
+ tok!(/\|/)
267
+ name = ident!
268
+ end
269
+ return ns, name
270
+ end
271
+
272
+ SELECTOR_PSEUDO_CLASSES = %w(not matches current any has host host-context).to_set
273
+
274
+ PREFIXED_SELECTOR_PSEUDO_CLASSES = %w(nth-child nth-last-child).to_set
275
+
276
+ SELECTOR_PSEUDO_ELEMENTS = %w(slotted).to_set
277
+
278
+ def pseudo
279
+ s = tok(/::?/)
280
+ return unless s
281
+ @expected = "pseudoclass or pseudoelement"
282
+ name = ident!
283
+ if tok(/\(/)
284
+ ss
285
+ deprefixed = deprefix(name)
286
+ if s == ':' && SELECTOR_PSEUDO_CLASSES.include?(deprefixed)
287
+ sel = selector_comma_sequence
288
+ elsif s == ':' && PREFIXED_SELECTOR_PSEUDO_CLASSES.include?(deprefixed)
289
+ arg, sel = prefixed_selector_pseudo
290
+ elsif s == '::' && SELECTOR_PSEUDO_ELEMENTS.include?(deprefixed)
291
+ sel = selector_comma_sequence
292
+ else
293
+ arg = expr!(:declaration_value).join
294
+ end
295
+
296
+ tok!(/\)/)
297
+ end
298
+ Selector::Pseudo.new(s == ':' ? :class : :element, name, arg, sel)
299
+ end
300
+
301
+ def prefixed_selector_pseudo
302
+ prefix = str do
303
+ expr = str {expr!(:a_n_plus_b)}
304
+ ss
305
+ return expr, nil unless tok(/of/)
306
+ ss
307
+ end
308
+ return prefix, expr!(:selector_comma_sequence)
309
+ end
310
+
311
+ def a_n_plus_b
312
+ if (parity = tok(/even|odd/i))
313
+ return parity
314
+ end
315
+
316
+ if tok(/[+-]?[0-9]+/)
317
+ ss
318
+ return true unless tok(/n/)
319
+ else
320
+ return unless tok(/[+-]?n/i)
321
+ end
322
+ ss
323
+
324
+ return true unless tok(/[+-]/)
325
+ ss
326
+ @expected = "number"
327
+ tok!(/[0-9]+/)
328
+ true
329
+ end
330
+
331
+ def keyframes_selector
332
+ ss
333
+ str do
334
+ return unless keyframes_selector_component
335
+ ss
336
+ while tok(/,/)
337
+ ss
338
+ expr!(:keyframes_selector_component)
339
+ ss
340
+ end
341
+ end
342
+ end
343
+
344
+ def keyframes_selector_component
345
+ ident || tok(PERCENTAGE)
346
+ end
347
+
348
+ @sass_script_parser = Class.new(Sass::Script::CssParser)
349
+ end
350
+ end
351
+ end
data/lib/sass/scss.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'sass/scss/rx'
2
+ require 'sass/scss/parser'
3
+ require 'sass/scss/static_parser'
4
+ require 'sass/scss/css_parser'
5
+
6
+ module Sass
7
+ # SCSS is the CSS syntax for Sass.
8
+ # It parses into the same syntax tree as Sass,
9
+ # and generates the same sort of output CSS.
10
+ #
11
+ # This module contains code for the parsing of SCSS.
12
+ # The evaluation is handled by the broader {Sass} module.
13
+ module SCSS; end
14
+ end
@@ -0,0 +1,112 @@
1
+ module Sass
2
+ module Selector
3
+ # The abstract parent class of the various selector sequence classes.
4
+ #
5
+ # All subclasses should implement a `members` method that returns an array
6
+ # of object that respond to `#line=` and `#filename=`, as well as a `to_s`
7
+ # method that returns the string representation of the selector.
8
+ class AbstractSequence
9
+ # The line of the Sass template on which this selector was declared.
10
+ #
11
+ # @return [Integer]
12
+ attr_reader :line
13
+
14
+ # The name of the file in which this selector was declared.
15
+ #
16
+ # @return [String, nil]
17
+ attr_reader :filename
18
+
19
+ # Sets the line of the Sass template on which this selector was declared.
20
+ # This also sets the line for all child selectors.
21
+ #
22
+ # @param line [Integer]
23
+ # @return [Integer]
24
+ def line=(line)
25
+ members.each {|m| m.line = line}
26
+ @line = line
27
+ end
28
+
29
+ # Sets the name of the file in which this selector was declared,
30
+ # or `nil` if it was not declared in a file (e.g. on stdin).
31
+ # This also sets the filename for all child selectors.
32
+ #
33
+ # @param filename [String, nil]
34
+ # @return [String, nil]
35
+ def filename=(filename)
36
+ members.each {|m| m.filename = filename}
37
+ @filename = filename
38
+ end
39
+
40
+ # Returns a hash code for this sequence.
41
+ #
42
+ # Subclasses should define `#_hash` rather than overriding this method,
43
+ # which automatically handles memoizing the result.
44
+ #
45
+ # @return [Integer]
46
+ def hash
47
+ @_hash ||= _hash
48
+ end
49
+
50
+ # Checks equality between this and another object.
51
+ #
52
+ # Subclasses should define `#_eql?` rather than overriding this method,
53
+ # which handles checking class equality and hash equality.
54
+ #
55
+ # @param other [Object] The object to test equality against
56
+ # @return [Boolean] Whether or not this is equal to `other`
57
+ def eql?(other)
58
+ other.class == self.class && other.hash == hash && _eql?(other)
59
+ end
60
+ alias_method :==, :eql?
61
+
62
+ # Whether or not this selector should be hidden due to containing a
63
+ # placeholder.
64
+ def invisible?
65
+ @invisible ||= members.any? do |m|
66
+ next m.invisible? if m.is_a?(AbstractSequence) || m.is_a?(Pseudo)
67
+ m.is_a?(Placeholder)
68
+ end
69
+ end
70
+
71
+ # Returns the selector string.
72
+ #
73
+ # @param opts [Hash] rendering options.
74
+ # @option opts [Symbol] :style The css rendering style.
75
+ # @option placeholders [Boolean] :placeholders
76
+ # Whether to include placeholder selectors. Defaults to `true`.
77
+ # @return [String]
78
+ def to_s(opts = {})
79
+ Sass::Util.abstract(self)
80
+ end
81
+
82
+ # Returns the specificity of the selector.
83
+ #
84
+ # The base is given by {Sass::Selector::SPECIFICITY_BASE}. This can be a
85
+ # number or a range representing possible specificities.
86
+ #
87
+ # @return [Integer, Range]
88
+ def specificity
89
+ _specificity(members)
90
+ end
91
+
92
+ protected
93
+
94
+ def _specificity(arr)
95
+ min = 0
96
+ max = 0
97
+ arr.each do |m|
98
+ next if m.is_a?(String)
99
+ spec = m.specificity
100
+ if spec.is_a?(Range)
101
+ min += spec.begin
102
+ max += spec.end
103
+ else
104
+ min += spec
105
+ max += spec
106
+ end
107
+ end
108
+ min == max ? min : (min..max)
109
+ end
110
+ end
111
+ end
112
+ end