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.
Files changed (260) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING +1 -1
  3. data/MIT-LICENSE +2 -2
  4. data/README.md +29 -17
  5. data/Rakefile +43 -9
  6. data/VERSION +1 -1
  7. data/VERSION_DATE +1 -0
  8. data/VERSION_NAME +1 -1
  9. data/bin/sass +6 -1
  10. data/bin/sass-convert +6 -1
  11. data/bin/scss +6 -1
  12. data/ext/mkrf_conf.rb +27 -0
  13. data/lib/sass/cache_stores/base.rb +7 -3
  14. data/lib/sass/cache_stores/chain.rb +3 -2
  15. data/lib/sass/cache_stores/filesystem.rb +5 -7
  16. data/lib/sass/cache_stores/memory.rb +1 -1
  17. data/lib/sass/cache_stores/null.rb +2 -2
  18. data/lib/sass/callbacks.rb +2 -1
  19. data/lib/sass/css.rb +168 -53
  20. data/lib/sass/engine.rb +502 -174
  21. data/lib/sass/environment.rb +151 -111
  22. data/lib/sass/error.rb +7 -7
  23. data/lib/sass/exec.rb +176 -60
  24. data/lib/sass/features.rb +40 -0
  25. data/lib/sass/importers/base.rb +46 -7
  26. data/lib/sass/importers/deprecated_path.rb +51 -0
  27. data/lib/sass/importers/filesystem.rb +113 -30
  28. data/lib/sass/importers.rb +1 -0
  29. data/lib/sass/logger/base.rb +30 -0
  30. data/lib/sass/logger/log_level.rb +45 -0
  31. data/lib/sass/logger.rb +12 -0
  32. data/lib/sass/media.rb +213 -0
  33. data/lib/sass/plugin/compiler.rb +194 -104
  34. data/lib/sass/plugin/configuration.rb +18 -25
  35. data/lib/sass/plugin/merb.rb +1 -1
  36. data/lib/sass/plugin/staleness_checker.rb +37 -11
  37. data/lib/sass/plugin.rb +10 -13
  38. data/lib/sass/railtie.rb +2 -1
  39. data/lib/sass/repl.rb +5 -6
  40. data/lib/sass/script/css_lexer.rb +8 -4
  41. data/lib/sass/script/css_parser.rb +5 -2
  42. data/lib/sass/script/functions.rb +1547 -618
  43. data/lib/sass/script/lexer.rb +122 -72
  44. data/lib/sass/script/parser.rb +304 -135
  45. data/lib/sass/script/tree/funcall.rb +306 -0
  46. data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
  47. data/lib/sass/script/tree/list_literal.rb +77 -0
  48. data/lib/sass/script/tree/literal.rb +45 -0
  49. data/lib/sass/script/tree/map_literal.rb +64 -0
  50. data/lib/sass/script/{node.rb → tree/node.rb} +30 -12
  51. data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
  52. data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
  53. data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
  54. data/lib/sass/script/tree/variable.rb +57 -0
  55. data/lib/sass/script/tree.rb +15 -0
  56. data/lib/sass/script/value/arg_list.rb +36 -0
  57. data/lib/sass/script/value/base.rb +238 -0
  58. data/lib/sass/script/value/bool.rb +40 -0
  59. data/lib/sass/script/{color.rb → value/color.rb} +256 -74
  60. data/lib/sass/script/value/deprecated_false.rb +55 -0
  61. data/lib/sass/script/value/helpers.rb +155 -0
  62. data/lib/sass/script/value/list.rb +128 -0
  63. data/lib/sass/script/value/map.rb +70 -0
  64. data/lib/sass/script/value/null.rb +49 -0
  65. data/lib/sass/script/{number.rb → value/number.rb} +115 -62
  66. data/lib/sass/script/{string.rb → value/string.rb} +9 -11
  67. data/lib/sass/script/value.rb +12 -0
  68. data/lib/sass/script.rb +35 -9
  69. data/lib/sass/scss/css_parser.rb +2 -12
  70. data/lib/sass/scss/parser.rb +657 -230
  71. data/lib/sass/scss/rx.rb +17 -12
  72. data/lib/sass/scss/static_parser.rb +37 -6
  73. data/lib/sass/scss.rb +0 -1
  74. data/lib/sass/selector/abstract_sequence.rb +35 -3
  75. data/lib/sass/selector/comma_sequence.rb +29 -14
  76. data/lib/sass/selector/sequence.rb +371 -74
  77. data/lib/sass/selector/simple.rb +28 -13
  78. data/lib/sass/selector/simple_sequence.rb +163 -36
  79. data/lib/sass/selector.rb +138 -36
  80. data/lib/sass/shared.rb +3 -5
  81. data/lib/sass/source/map.rb +196 -0
  82. data/lib/sass/source/position.rb +39 -0
  83. data/lib/sass/source/range.rb +41 -0
  84. data/lib/sass/stack.rb +126 -0
  85. data/lib/sass/supports.rb +228 -0
  86. data/lib/sass/tree/at_root_node.rb +82 -0
  87. data/lib/sass/tree/comment_node.rb +34 -29
  88. data/lib/sass/tree/content_node.rb +9 -0
  89. data/lib/sass/tree/css_import_node.rb +60 -0
  90. data/lib/sass/tree/debug_node.rb +3 -3
  91. data/lib/sass/tree/directive_node.rb +33 -3
  92. data/lib/sass/tree/each_node.rb +9 -9
  93. data/lib/sass/tree/extend_node.rb +20 -6
  94. data/lib/sass/tree/for_node.rb +6 -6
  95. data/lib/sass/tree/function_node.rb +12 -4
  96. data/lib/sass/tree/if_node.rb +2 -15
  97. data/lib/sass/tree/import_node.rb +11 -5
  98. data/lib/sass/tree/media_node.rb +27 -11
  99. data/lib/sass/tree/mixin_def_node.rb +15 -4
  100. data/lib/sass/tree/mixin_node.rb +27 -7
  101. data/lib/sass/tree/node.rb +69 -35
  102. data/lib/sass/tree/prop_node.rb +47 -31
  103. data/lib/sass/tree/return_node.rb +4 -3
  104. data/lib/sass/tree/root_node.rb +20 -4
  105. data/lib/sass/tree/rule_node.rb +37 -26
  106. data/lib/sass/tree/supports_node.rb +38 -0
  107. data/lib/sass/tree/trace_node.rb +33 -0
  108. data/lib/sass/tree/variable_node.rb +10 -4
  109. data/lib/sass/tree/visitors/base.rb +5 -8
  110. data/lib/sass/tree/visitors/check_nesting.rb +67 -52
  111. data/lib/sass/tree/visitors/convert.rb +134 -53
  112. data/lib/sass/tree/visitors/cssize.rb +245 -51
  113. data/lib/sass/tree/visitors/deep_copy.rb +102 -0
  114. data/lib/sass/tree/visitors/extend.rb +68 -0
  115. data/lib/sass/tree/visitors/perform.rb +331 -105
  116. data/lib/sass/tree/visitors/set_options.rb +125 -0
  117. data/lib/sass/tree/visitors/to_css.rb +259 -95
  118. data/lib/sass/tree/warn_node.rb +3 -3
  119. data/lib/sass/tree/while_node.rb +3 -3
  120. data/lib/sass/util/cross_platform_random.rb +19 -0
  121. data/lib/sass/util/multibyte_string_scanner.rb +157 -0
  122. data/lib/sass/util/normalized_map.rb +130 -0
  123. data/lib/sass/util/ordered_hash.rb +192 -0
  124. data/lib/sass/util/subset_map.rb +11 -2
  125. data/lib/sass/util/test.rb +9 -0
  126. data/lib/sass/util.rb +565 -39
  127. data/lib/sass/version.rb +27 -15
  128. data/lib/sass.rb +39 -4
  129. data/test/sass/cache_test.rb +15 -0
  130. data/test/sass/compiler_test.rb +223 -0
  131. data/test/sass/conversion_test.rb +901 -107
  132. data/test/sass/css2sass_test.rb +94 -0
  133. data/test/sass/engine_test.rb +1059 -164
  134. data/test/sass/exec_test.rb +86 -0
  135. data/test/sass/extend_test.rb +933 -837
  136. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  137. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  138. data/test/sass/functions_test.rb +995 -136
  139. data/test/sass/importer_test.rb +338 -18
  140. data/test/sass/logger_test.rb +58 -0
  141. data/test/sass/more_results/more_import.css +2 -2
  142. data/test/sass/plugin_test.rb +114 -30
  143. data/test/sass/results/cached_import_option.css +3 -0
  144. data/test/sass/results/filename_fn.css +3 -0
  145. data/test/sass/results/import.css +2 -2
  146. data/test/sass/results/import_charset.css +1 -0
  147. data/test/sass/results/import_charset_1_8.css +1 -0
  148. data/test/sass/results/import_charset_ibm866.css +1 -0
  149. data/test/sass/results/import_content.css +1 -0
  150. data/test/sass/results/script.css +1 -1
  151. data/test/sass/results/scss_import.css +2 -2
  152. data/test/sass/results/units.css +2 -2
  153. data/test/sass/script_conversion_test.rb +43 -1
  154. data/test/sass/script_test.rb +380 -36
  155. data/test/sass/scss/css_test.rb +257 -75
  156. data/test/sass/scss/scss_test.rb +2322 -110
  157. data/test/sass/source_map_test.rb +887 -0
  158. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  159. data/test/sass/templates/_double_import_loop2.sass +1 -0
  160. data/test/sass/templates/_filename_fn_import.scss +11 -0
  161. data/test/sass/templates/_imported_content.sass +3 -0
  162. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  163. data/test/sass/templates/bork5.sass +3 -0
  164. data/test/sass/templates/cached_import_option.scss +3 -0
  165. data/test/sass/templates/double_import_loop1.sass +1 -0
  166. data/test/sass/templates/filename_fn.scss +18 -0
  167. data/test/sass/templates/import_charset.sass +2 -0
  168. data/test/sass/templates/import_charset_1_8.sass +2 -0
  169. data/test/sass/templates/import_charset_ibm866.sass +2 -0
  170. data/test/sass/templates/import_content.sass +4 -0
  171. data/test/sass/templates/same_name_different_ext.sass +2 -0
  172. data/test/sass/templates/same_name_different_ext.scss +1 -0
  173. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  174. data/test/sass/templates/single_import_loop.sass +1 -0
  175. data/test/sass/templates/subdir/import_up1.scss +1 -0
  176. data/test/sass/templates/subdir/import_up2.scss +1 -0
  177. data/test/sass/test_helper.rb +1 -1
  178. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  179. data/test/sass/util/normalized_map_test.rb +51 -0
  180. data/test/sass/util_test.rb +183 -0
  181. data/test/sass/value_helpers_test.rb +181 -0
  182. data/test/test_helper.rb +45 -5
  183. data/vendor/listen/CHANGELOG.md +228 -0
  184. data/vendor/listen/CONTRIBUTING.md +38 -0
  185. data/vendor/listen/Gemfile +30 -0
  186. data/vendor/listen/Guardfile +8 -0
  187. data/vendor/{fssm → listen}/LICENSE +1 -1
  188. data/vendor/listen/README.md +315 -0
  189. data/vendor/listen/Rakefile +47 -0
  190. data/vendor/listen/Vagrantfile +96 -0
  191. data/vendor/listen/lib/listen/adapter.rb +214 -0
  192. data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
  193. data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
  194. data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
  195. data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
  196. data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
  197. data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
  198. data/vendor/listen/lib/listen/directory_record.rb +371 -0
  199. data/vendor/listen/lib/listen/listener.rb +225 -0
  200. data/vendor/listen/lib/listen/multi_listener.rb +143 -0
  201. data/vendor/listen/lib/listen/turnstile.rb +28 -0
  202. data/vendor/listen/lib/listen/version.rb +3 -0
  203. data/vendor/listen/lib/listen.rb +40 -0
  204. data/vendor/listen/listen.gemspec +22 -0
  205. data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
  206. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  207. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
  208. data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
  209. data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
  210. data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
  211. data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
  212. data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
  213. data/vendor/listen/spec/listen/listener_spec.rb +169 -0
  214. data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
  215. data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
  216. data/vendor/listen/spec/listen_spec.rb +73 -0
  217. data/vendor/listen/spec/spec_helper.rb +21 -0
  218. data/vendor/listen/spec/support/adapter_helper.rb +629 -0
  219. data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
  220. data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
  221. data/vendor/listen/spec/support/listeners_helper.rb +156 -0
  222. data/vendor/listen/spec/support/platform_helper.rb +15 -0
  223. metadata +344 -271
  224. data/lib/sass/less.rb +0 -382
  225. data/lib/sass/script/bool.rb +0 -18
  226. data/lib/sass/script/funcall.rb +0 -162
  227. data/lib/sass/script/list.rb +0 -76
  228. data/lib/sass/script/literal.rb +0 -245
  229. data/lib/sass/script/variable.rb +0 -54
  230. data/lib/sass/scss/sass_parser.rb +0 -11
  231. data/test/sass/less_conversion_test.rb +0 -653
  232. data/vendor/fssm/README.markdown +0 -55
  233. data/vendor/fssm/Rakefile +0 -59
  234. data/vendor/fssm/VERSION.yml +0 -5
  235. data/vendor/fssm/example.rb +0 -9
  236. data/vendor/fssm/fssm.gemspec +0 -77
  237. data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
  238. data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
  239. data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
  240. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
  241. data/vendor/fssm/lib/fssm/monitor.rb +0 -26
  242. data/vendor/fssm/lib/fssm/path.rb +0 -91
  243. data/vendor/fssm/lib/fssm/pathname.rb +0 -502
  244. data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
  245. data/vendor/fssm/lib/fssm/state/file.rb +0 -24
  246. data/vendor/fssm/lib/fssm/support.rb +0 -63
  247. data/vendor/fssm/lib/fssm/tree.rb +0 -176
  248. data/vendor/fssm/lib/fssm.rb +0 -33
  249. data/vendor/fssm/profile/prof-cache.rb +0 -40
  250. data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
  251. data/vendor/fssm/profile/prof-pathname.rb +0 -68
  252. data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
  253. data/vendor/fssm/profile/prof.html +0 -2379
  254. data/vendor/fssm/spec/path_spec.rb +0 -75
  255. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  256. data/vendor/fssm/spec/root/file.css +0 -0
  257. data/vendor/fssm/spec/root/file.rb +0 -0
  258. data/vendor/fssm/spec/root/file.yml +0 -0
  259. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  260. data/vendor/fssm/spec/spec_helper.rb +0 -14
data/lib/sass/scss/rx.rb CHANGED
@@ -22,7 +22,7 @@ module Sass
22
22
  out << escape_char(value.slice!(0...1))
23
23
  end
24
24
  out << value.gsub(/[^a-zA-Z0-9_-]/) {|c| escape_char c}
25
- return out
25
+ out
26
26
  end
27
27
 
28
28
  # Escapes a single character for a CSS identifier.
@@ -32,7 +32,7 @@ module Sass
32
32
  # @private
33
33
  def self.escape_char(c)
34
34
  return "\\%06x" % Sass::Util.ord(c) unless c =~ /[ -\/:-~]/
35
- return "\\#{c}"
35
+ "\\#{c}"
36
36
  end
37
37
 
38
38
  # Creates a Regexp from a plain text string,
@@ -51,6 +51,8 @@ module Sass
51
51
  UNICODE = /\\#{H}{1,6}[ \t\r\n\f]?/
52
52
  s = if Sass::Util.ruby1_8?
53
53
  '\200-\377'
54
+ elsif Sass::Util.macruby?
55
+ '\u0080-\uD7FF\uE000-\uFFFD\U00010000-\U0010FFFF'
54
56
  else
55
57
  '\u{80}-\u{D7FF}\u{E000}-\u{FFFD}\u{10000}-\u{10FFFF}'
56
58
  end
@@ -78,8 +80,8 @@ module Sass
78
80
 
79
81
  S = /[ \t\r\n\f]+/
80
82
 
81
- COMMENT = /\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\//
82
- SINGLE_LINE_COMMENT = /\/\/.*(\n[ \t]*\/\/.*)*/
83
+ COMMENT = %r{/\*[^*]*\*+(?:[^/][^*]*\*+)*/}
84
+ SINGLE_LINE_COMMENT = %r{//.*(\n[ \t]*//.*)*}
83
85
 
84
86
  CDO = quote("<!--")
85
87
  CDC = quote("-->")
@@ -92,7 +94,6 @@ module Sass
92
94
  HASH = /##{NAME}/
93
95
 
94
96
  IMPORTANT = /!#{W}important/i
95
- DEFAULT = /!#{W}default/i
96
97
 
97
98
  NUMBER = /#{NUM}(?:#{IDENT}|%)?/
98
99
 
@@ -107,21 +108,25 @@ module Sass
107
108
  TILDE = /#{W}~/
108
109
  NOT = quote(":not(", Regexp::IGNORECASE)
109
110
 
111
+ # Defined in https://developer.mozilla.org/en/CSS/@-moz-document as a
112
+ # non-standard version of http://www.w3.org/TR/css3-conditional/
113
+ URL_PREFIX = /url-prefix\(#{W}(?:#{STRING}|#{URL})#{W}\)/i
114
+ DOMAIN = /domain\(#{W}(?:#{STRING}|#{URL})#{W}\)/i
115
+
110
116
  # Custom
111
117
  HEXCOLOR = /\#[0-9a-fA-F]+/
112
118
  INTERP_START = /#\{/
113
- MOZ_ANY = quote(":-moz-any(", Regexp::IGNORECASE)
119
+ ANY = /:(-[-\w]+-)?any\(/i
120
+ OPTIONAL = /!#{W}optional/i
114
121
 
122
+ IDENT_HYPHEN_INTERP = /-(#\{)/
115
123
  STRING1_NOINTERP = /\"((?:[^\n\r\f\\"#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\"/
116
124
  STRING2_NOINTERP = /\'((?:[^\n\r\f\\'#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\'/
117
125
  STRING_NOINTERP = /#{STRING1_NOINTERP}|#{STRING2_NOINTERP}/
118
- # Can't use IDENT here, because it seems to take exponential time on 1.8.
119
- # We could use it for 1.9 only, but I don't want to introduce a cross-version
120
- # behavior difference.
121
- # In any case, almost all CSS idents will be matched by this.
122
- STATIC_VALUE = /(-?#{NMSTART}|#{STRING_NOINTERP}|\s(?!%)|#[a-f0-9]|[,%]|#{NUM})+(?=[;}])/i
123
126
 
124
- STATIC_SELECTOR = /(#{NMCHAR}|\s|[,>+*]|[:#.]#{NMSTART})+(?=[{])/i
127
+ STATIC_COMPONENT = /#{IDENT}|#{STRING_NOINTERP}|#{HEXCOLOR}|[+-]?#{NUMBER}|\!important/i
128
+ STATIC_VALUE = /#{STATIC_COMPONENT}(\s*[\s,\/]\s*#{STATIC_COMPONENT})*([;}])/i
129
+ STATIC_SELECTOR = /(#{NMCHAR}|[ \t]|[,>+*]|[:#.]#{NMSTART}){1,50}([{])/i
125
130
  end
126
131
  end
127
132
  end
@@ -1,3 +1,5 @@
1
+ require 'sass/script/css_parser'
2
+
1
3
  module Sass
2
4
  module SCSS
3
5
  # A parser for a static SCSS tree.
@@ -13,28 +15,57 @@ module Sass
13
15
  # Used for error reporting.
14
16
  # @return [Selector::CommaSequence] The parsed selector
15
17
  # @raise [Sass::SyntaxError] if there's a syntax error in the selector
16
- def parse_selector(filename)
18
+ def parse_selector
17
19
  init_scanner!
18
20
  seq = expr!(:selector_comma_sequence)
19
21
  expected("selector") unless @scanner.eos?
20
22
  seq.line = @line
21
- seq.filename = filename
23
+ seq.filename = @filename
22
24
  seq
23
25
  end
24
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
+
25
44
  private
26
45
 
46
+ def moz_document_function
47
+ val = tok(URI) || tok(URL_PREFIX) || tok(DOMAIN) || function(!:allow_var)
48
+ return unless val
49
+ ss
50
+ [val]
51
+ end
52
+
27
53
  def variable; nil; end
28
54
  def script_value; nil; end
29
55
  def interpolation; nil; end
30
- def interp_string; s = tok(STRING) and [s]; end
31
- def interp_ident(ident = IDENT); s = tok(ident) and [s]; end
56
+ def var_expr; nil; end
57
+ def interp_string; (s = tok(STRING)) && [s]; end
58
+ def interp_uri; (s = tok(URI)) && [s]; end
59
+ def interp_ident(ident = IDENT); (s = tok(ident)) && [s]; end
32
60
  def use_css_import?; true; end
33
61
 
34
- def special_directive(name)
35
- return unless %w[media import charset].include?(name)
62
+ def special_directive(name, start_pos)
63
+ return unless %w[media import charset -moz-document].include?(name)
36
64
  super
37
65
  end
66
+
67
+ @sass_script_parser = Class.new(Sass::Script::CssParser)
68
+ @sass_script_parser.send(:include, ScriptParser)
38
69
  end
39
70
  end
40
71
  end
data/lib/sass/scss.rb CHANGED
@@ -2,7 +2,6 @@ require 'sass/scss/rx'
2
2
  require 'sass/scss/script_lexer'
3
3
  require 'sass/scss/script_parser'
4
4
  require 'sass/scss/parser'
5
- require 'sass/scss/sass_parser'
6
5
  require 'sass/scss/static_parser'
7
6
  require 'sass/scss/css_parser'
8
7
 
@@ -2,8 +2,9 @@ module Sass
2
2
  module Selector
3
3
  # The abstract parent class of the various selector sequence classes.
4
4
  #
5
- # All subclasses should implement a `members` method
6
- # that returns an array of object that respond to `#line=` and `#filename=`.
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_a`
7
+ # method that returns an array of strings and script nodes.
7
8
  class AbstractSequence
8
9
  # The line of the Sass template on which this selector was declared.
9
10
  #
@@ -54,9 +55,40 @@ module Sass
54
55
  # @param other [Object] The object to test equality against
55
56
  # @return [Boolean] Whether or not this is equal to `other`
56
57
  def eql?(other)
57
- other.class == self.class && other.hash == self.hash && _eql?(other)
58
+ other.class == self.class && other.hash == hash && _eql?(other)
58
59
  end
59
60
  alias_method :==, :eql?
61
+
62
+ # Whether or not this selector sequence contains a placeholder selector.
63
+ # Checks recursively.
64
+ def has_placeholder?
65
+ @has_placeholder ||=
66
+ members.any? {|m| m.is_a?(AbstractSequence) ? m.has_placeholder? : m.is_a?(Placeholder)}
67
+ end
68
+
69
+ # Converts the selector into a string. This is the standard selector
70
+ # string, along with any SassScript interpolation that may exist.
71
+ #
72
+ # @return [String]
73
+ def to_s
74
+ to_a.map {|e| e.is_a?(Sass::Script::Tree::Node) ? "\#{#{e.to_sass}}" : e}.join
75
+ end
76
+
77
+ # Returns the specificity of the selector as an integer. The base is given
78
+ # by {Sass::Selector::SPECIFICITY_BASE}.
79
+ #
80
+ # @return [Fixnum]
81
+ def specificity
82
+ _specificity(members)
83
+ end
84
+
85
+ protected
86
+
87
+ def _specificity(arr)
88
+ spec = 0
89
+ arr.map {|m| spec += m.is_a?(String) ? 0 : m.specificity}
90
+ spec
91
+ end
60
92
  end
61
93
  end
62
94
  end
@@ -18,24 +18,28 @@ module Sass
18
18
  # handling commas appropriately.
19
19
  #
20
20
  # @param super_cseq [CommaSequence] The parent selector
21
+ # @param implicit_parent [Boolean] Whether the the parent
22
+ # selector should automatically be prepended to the resolved
23
+ # selector if it contains no parent refs.
21
24
  # @return [CommaSequence] This selector, with parent references resolved
22
25
  # @raise [Sass::SyntaxError] If a parent selector is invalid
23
- def resolve_parent_refs(super_cseq)
26
+ def resolve_parent_refs(super_cseq, implicit_parent = true)
24
27
  if super_cseq.nil?
25
28
  if @members.any? do |sel|
26
- sel.members.any? do |sel_or_op|
27
- sel_or_op.is_a?(SimpleSequence) && sel_or_op.members.any? {|ssel| ssel.is_a?(Parent)}
28
- end
29
- end
30
- raise Sass::SyntaxError.new("Base-level rules cannot contain the parent-selector-referencing character '&'.")
29
+ sel.members.any? do |sel_or_op|
30
+ sel_or_op.is_a?(SimpleSequence) &&
31
+ sel_or_op.members.any? {|ssel| ssel.is_a?(Parent)}
32
+ end
33
+ end
34
+ raise Sass::SyntaxError.new(
35
+ "Base-level rules cannot contain the parent-selector-referencing character '&'.")
31
36
  end
32
37
  return self
33
38
  end
34
39
 
35
- CommaSequence.new(
36
- super_cseq.members.map do |super_seq|
37
- @members.map {|seq| seq.resolve_parent_refs(super_seq)}
38
- end.flatten)
40
+ CommaSequence.new(Sass::Util.flatten_vertically(@members.map do |seq|
41
+ seq.resolve_parent_refs(super_cseq, implicit_parent).members
42
+ end))
39
43
  end
40
44
 
41
45
  # Non-destrucively extends this selector with the extensions specified in a hash
@@ -44,12 +48,23 @@ module Sass
44
48
  # @todo Link this to the reference documentation on `@extend`
45
49
  # when such a thing exists.
46
50
  #
47
- # @param extends [Sass::Util::SubsetMap{Selector::Simple => Selector::Sequence}]
51
+ # @param extends [Sass::Util::SubsetMap{Selector::Simple =>
52
+ # Sass::Tree::Visitors::Cssize::Extend}]
48
53
  # The extensions to perform on this selector
54
+ # @param parent_directives [Array<Sass::Tree::DirectiveNode>]
55
+ # The directives containing this selector.
49
56
  # @return [CommaSequence] A copy of this selector,
50
57
  # with extensions made according to `extends`
51
- def do_extend(extends)
52
- CommaSequence.new(members.map {|seq| seq.do_extend(extends)}.flatten)
58
+ def do_extend(extends, parent_directives)
59
+ CommaSequence.new(members.map do |seq|
60
+ extended = seq.do_extend(extends, parent_directives)
61
+ # First Law of Extend: the result of extending a selector should
62
+ # always contain the base selector.
63
+ #
64
+ # See https://github.com/nex3/sass/issues/324.
65
+ extended.unshift seq unless seq.has_placeholder? || extended.include?(seq)
66
+ extended
67
+ end.flatten)
53
68
  end
54
69
 
55
70
  # Returns a string representation of the sequence.
@@ -74,7 +89,7 @@ module Sass
74
89
  end
75
90
 
76
91
  def _eql?(other)
77
- other.class == self.class && other.members.eql?(self.members)
92
+ other.class == self.class && other.members.eql?(members)
78
93
  end
79
94
  end
80
95
  end