aliddle-sass 1.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 (238) hide show
  1. data/.yardopts +11 -0
  2. data/CONTRIBUTING +3 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +201 -0
  5. data/Rakefile +347 -0
  6. data/VERSION +1 -0
  7. data/VERSION_NAME +1 -0
  8. data/bin/sass +9 -0
  9. data/bin/sass-convert +8 -0
  10. data/bin/scss +9 -0
  11. data/extra/update_watch.rb +13 -0
  12. data/init.rb +18 -0
  13. data/lib/sass.rb +95 -0
  14. data/lib/sass/cache_stores.rb +15 -0
  15. data/lib/sass/cache_stores/base.rb +88 -0
  16. data/lib/sass/cache_stores/chain.rb +33 -0
  17. data/lib/sass/cache_stores/filesystem.rb +60 -0
  18. data/lib/sass/cache_stores/memory.rb +47 -0
  19. data/lib/sass/cache_stores/null.rb +25 -0
  20. data/lib/sass/callbacks.rb +66 -0
  21. data/lib/sass/css.rb +409 -0
  22. data/lib/sass/engine.rb +928 -0
  23. data/lib/sass/environment.rb +101 -0
  24. data/lib/sass/error.rb +201 -0
  25. data/lib/sass/exec.rb +707 -0
  26. data/lib/sass/importers.rb +22 -0
  27. data/lib/sass/importers/base.rb +139 -0
  28. data/lib/sass/importers/filesystem.rb +190 -0
  29. data/lib/sass/logger.rb +15 -0
  30. data/lib/sass/logger/base.rb +32 -0
  31. data/lib/sass/logger/log_level.rb +49 -0
  32. data/lib/sass/media.rb +213 -0
  33. data/lib/sass/plugin.rb +132 -0
  34. data/lib/sass/plugin/compiler.rb +406 -0
  35. data/lib/sass/plugin/configuration.rb +123 -0
  36. data/lib/sass/plugin/generic.rb +15 -0
  37. data/lib/sass/plugin/merb.rb +48 -0
  38. data/lib/sass/plugin/rack.rb +60 -0
  39. data/lib/sass/plugin/rails.rb +47 -0
  40. data/lib/sass/plugin/staleness_checker.rb +183 -0
  41. data/lib/sass/railtie.rb +9 -0
  42. data/lib/sass/repl.rb +57 -0
  43. data/lib/sass/root.rb +7 -0
  44. data/lib/sass/script.rb +39 -0
  45. data/lib/sass/script/arg_list.rb +52 -0
  46. data/lib/sass/script/bool.rb +18 -0
  47. data/lib/sass/script/color.rb +606 -0
  48. data/lib/sass/script/css_lexer.rb +29 -0
  49. data/lib/sass/script/css_parser.rb +31 -0
  50. data/lib/sass/script/funcall.rb +237 -0
  51. data/lib/sass/script/functions.rb +1543 -0
  52. data/lib/sass/script/interpolation.rb +79 -0
  53. data/lib/sass/script/lexer.rb +348 -0
  54. data/lib/sass/script/list.rb +85 -0
  55. data/lib/sass/script/literal.rb +221 -0
  56. data/lib/sass/script/node.rb +99 -0
  57. data/lib/sass/script/null.rb +37 -0
  58. data/lib/sass/script/number.rb +453 -0
  59. data/lib/sass/script/operation.rb +110 -0
  60. data/lib/sass/script/parser.rb +495 -0
  61. data/lib/sass/script/string.rb +51 -0
  62. data/lib/sass/script/string_interpolation.rb +103 -0
  63. data/lib/sass/script/unary_operation.rb +69 -0
  64. data/lib/sass/script/variable.rb +58 -0
  65. data/lib/sass/scss.rb +16 -0
  66. data/lib/sass/scss/css_parser.rb +36 -0
  67. data/lib/sass/scss/parser.rb +1179 -0
  68. data/lib/sass/scss/rx.rb +133 -0
  69. data/lib/sass/scss/script_lexer.rb +15 -0
  70. data/lib/sass/scss/script_parser.rb +25 -0
  71. data/lib/sass/scss/static_parser.rb +54 -0
  72. data/lib/sass/selector.rb +452 -0
  73. data/lib/sass/selector/abstract_sequence.rb +94 -0
  74. data/lib/sass/selector/comma_sequence.rb +92 -0
  75. data/lib/sass/selector/sequence.rb +507 -0
  76. data/lib/sass/selector/simple.rb +119 -0
  77. data/lib/sass/selector/simple_sequence.rb +212 -0
  78. data/lib/sass/shared.rb +76 -0
  79. data/lib/sass/supports.rb +229 -0
  80. data/lib/sass/tree/charset_node.rb +22 -0
  81. data/lib/sass/tree/comment_node.rb +82 -0
  82. data/lib/sass/tree/content_node.rb +9 -0
  83. data/lib/sass/tree/css_import_node.rb +60 -0
  84. data/lib/sass/tree/debug_node.rb +18 -0
  85. data/lib/sass/tree/directive_node.rb +42 -0
  86. data/lib/sass/tree/each_node.rb +24 -0
  87. data/lib/sass/tree/extend_node.rb +36 -0
  88. data/lib/sass/tree/for_node.rb +36 -0
  89. data/lib/sass/tree/function_node.rb +34 -0
  90. data/lib/sass/tree/if_node.rb +52 -0
  91. data/lib/sass/tree/import_node.rb +75 -0
  92. data/lib/sass/tree/media_node.rb +58 -0
  93. data/lib/sass/tree/mixin_def_node.rb +38 -0
  94. data/lib/sass/tree/mixin_node.rb +39 -0
  95. data/lib/sass/tree/node.rb +196 -0
  96. data/lib/sass/tree/prop_node.rb +152 -0
  97. data/lib/sass/tree/return_node.rb +18 -0
  98. data/lib/sass/tree/root_node.rb +28 -0
  99. data/lib/sass/tree/rule_node.rb +132 -0
  100. data/lib/sass/tree/supports_node.rb +51 -0
  101. data/lib/sass/tree/trace_node.rb +32 -0
  102. data/lib/sass/tree/variable_node.rb +30 -0
  103. data/lib/sass/tree/visitors/base.rb +75 -0
  104. data/lib/sass/tree/visitors/check_nesting.rb +147 -0
  105. data/lib/sass/tree/visitors/convert.rb +316 -0
  106. data/lib/sass/tree/visitors/cssize.rb +229 -0
  107. data/lib/sass/tree/visitors/deep_copy.rb +102 -0
  108. data/lib/sass/tree/visitors/extend.rb +68 -0
  109. data/lib/sass/tree/visitors/perform.rb +446 -0
  110. data/lib/sass/tree/visitors/set_options.rb +125 -0
  111. data/lib/sass/tree/visitors/to_css.rb +230 -0
  112. data/lib/sass/tree/warn_node.rb +18 -0
  113. data/lib/sass/tree/while_node.rb +18 -0
  114. data/lib/sass/util.rb +906 -0
  115. data/lib/sass/util/multibyte_string_scanner.rb +155 -0
  116. data/lib/sass/util/subset_map.rb +109 -0
  117. data/lib/sass/util/test.rb +10 -0
  118. data/lib/sass/version.rb +126 -0
  119. data/rails/init.rb +1 -0
  120. data/test/Gemfile +3 -0
  121. data/test/Gemfile.lock +10 -0
  122. data/test/sass/cache_test.rb +89 -0
  123. data/test/sass/callbacks_test.rb +61 -0
  124. data/test/sass/conversion_test.rb +1760 -0
  125. data/test/sass/css2sass_test.rb +439 -0
  126. data/test/sass/data/hsl-rgb.txt +319 -0
  127. data/test/sass/engine_test.rb +3243 -0
  128. data/test/sass/exec_test.rb +86 -0
  129. data/test/sass/extend_test.rb +1461 -0
  130. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  131. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  132. data/test/sass/functions_test.rb +1139 -0
  133. data/test/sass/importer_test.rb +192 -0
  134. data/test/sass/logger_test.rb +58 -0
  135. data/test/sass/mock_importer.rb +49 -0
  136. data/test/sass/more_results/more1.css +9 -0
  137. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  138. data/test/sass/more_results/more_import.css +29 -0
  139. data/test/sass/more_templates/_more_partial.sass +2 -0
  140. data/test/sass/more_templates/more1.sass +23 -0
  141. data/test/sass/more_templates/more_import.sass +11 -0
  142. data/test/sass/plugin_test.rb +550 -0
  143. data/test/sass/results/alt.css +4 -0
  144. data/test/sass/results/basic.css +9 -0
  145. data/test/sass/results/cached_import_option.css +3 -0
  146. data/test/sass/results/compact.css +5 -0
  147. data/test/sass/results/complex.css +86 -0
  148. data/test/sass/results/compressed.css +1 -0
  149. data/test/sass/results/expanded.css +19 -0
  150. data/test/sass/results/filename_fn.css +3 -0
  151. data/test/sass/results/if.css +3 -0
  152. data/test/sass/results/import.css +31 -0
  153. data/test/sass/results/import_charset.css +5 -0
  154. data/test/sass/results/import_charset_1_8.css +5 -0
  155. data/test/sass/results/import_charset_ibm866.css +5 -0
  156. data/test/sass/results/import_content.css +1 -0
  157. data/test/sass/results/line_numbers.css +49 -0
  158. data/test/sass/results/mixins.css +95 -0
  159. data/test/sass/results/multiline.css +24 -0
  160. data/test/sass/results/nested.css +22 -0
  161. data/test/sass/results/options.css +1 -0
  162. data/test/sass/results/parent_ref.css +13 -0
  163. data/test/sass/results/script.css +16 -0
  164. data/test/sass/results/scss_import.css +31 -0
  165. data/test/sass/results/scss_importee.css +2 -0
  166. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  167. data/test/sass/results/subdir/subdir.css +3 -0
  168. data/test/sass/results/units.css +11 -0
  169. data/test/sass/results/warn.css +0 -0
  170. data/test/sass/results/warn_imported.css +0 -0
  171. data/test/sass/script_conversion_test.rb +299 -0
  172. data/test/sass/script_test.rb +591 -0
  173. data/test/sass/scss/css_test.rb +1093 -0
  174. data/test/sass/scss/rx_test.rb +156 -0
  175. data/test/sass/scss/scss_test.rb +2043 -0
  176. data/test/sass/scss/test_helper.rb +37 -0
  177. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  178. data/test/sass/templates/_double_import_loop2.sass +1 -0
  179. data/test/sass/templates/_filename_fn_import.scss +11 -0
  180. data/test/sass/templates/_imported_charset_ibm866.sass +4 -0
  181. data/test/sass/templates/_imported_charset_utf8.sass +4 -0
  182. data/test/sass/templates/_imported_content.sass +3 -0
  183. data/test/sass/templates/_partial.sass +2 -0
  184. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  185. data/test/sass/templates/alt.sass +16 -0
  186. data/test/sass/templates/basic.sass +23 -0
  187. data/test/sass/templates/bork1.sass +2 -0
  188. data/test/sass/templates/bork2.sass +2 -0
  189. data/test/sass/templates/bork3.sass +2 -0
  190. data/test/sass/templates/bork4.sass +2 -0
  191. data/test/sass/templates/bork5.sass +3 -0
  192. data/test/sass/templates/cached_import_option.scss +3 -0
  193. data/test/sass/templates/compact.sass +17 -0
  194. data/test/sass/templates/complex.sass +305 -0
  195. data/test/sass/templates/compressed.sass +15 -0
  196. data/test/sass/templates/double_import_loop1.sass +1 -0
  197. data/test/sass/templates/expanded.sass +17 -0
  198. data/test/sass/templates/filename_fn.scss +18 -0
  199. data/test/sass/templates/if.sass +11 -0
  200. data/test/sass/templates/import.sass +12 -0
  201. data/test/sass/templates/import_charset.sass +9 -0
  202. data/test/sass/templates/import_charset_1_8.sass +6 -0
  203. data/test/sass/templates/import_charset_ibm866.sass +11 -0
  204. data/test/sass/templates/import_content.sass +4 -0
  205. data/test/sass/templates/importee.less +2 -0
  206. data/test/sass/templates/importee.sass +19 -0
  207. data/test/sass/templates/line_numbers.sass +13 -0
  208. data/test/sass/templates/mixin_bork.sass +5 -0
  209. data/test/sass/templates/mixins.sass +76 -0
  210. data/test/sass/templates/multiline.sass +20 -0
  211. data/test/sass/templates/nested.sass +25 -0
  212. data/test/sass/templates/nested_bork1.sass +2 -0
  213. data/test/sass/templates/nested_bork2.sass +2 -0
  214. data/test/sass/templates/nested_bork3.sass +2 -0
  215. data/test/sass/templates/nested_bork4.sass +2 -0
  216. data/test/sass/templates/nested_import.sass +2 -0
  217. data/test/sass/templates/nested_mixin_bork.sass +6 -0
  218. data/test/sass/templates/options.sass +2 -0
  219. data/test/sass/templates/parent_ref.sass +25 -0
  220. data/test/sass/templates/same_name_different_ext.sass +2 -0
  221. data/test/sass/templates/same_name_different_ext.scss +1 -0
  222. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  223. data/test/sass/templates/script.sass +101 -0
  224. data/test/sass/templates/scss_import.scss +11 -0
  225. data/test/sass/templates/scss_importee.scss +1 -0
  226. data/test/sass/templates/single_import_loop.sass +1 -0
  227. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  228. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  229. data/test/sass/templates/subdir/subdir.sass +6 -0
  230. data/test/sass/templates/units.sass +11 -0
  231. data/test/sass/templates/warn.sass +3 -0
  232. data/test/sass/templates/warn_imported.sass +4 -0
  233. data/test/sass/test_helper.rb +8 -0
  234. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  235. data/test/sass/util/subset_map_test.rb +91 -0
  236. data/test/sass/util_test.rb +313 -0
  237. data/test/test_helper.rb +80 -0
  238. metadata +348 -0
@@ -0,0 +1,133 @@
1
+ module Sass
2
+ module SCSS
3
+ # A module containing regular expressions used
4
+ # for lexing tokens in an SCSS document.
5
+ # Most of these are taken from [the CSS3 spec](http://www.w3.org/TR/css3-syntax/#lexical),
6
+ # although some have been modified for various reasons.
7
+ module RX
8
+ # Takes a string and returns a CSS identifier
9
+ # that will have the value of the given string.
10
+ #
11
+ # @param str [String] The string to escape
12
+ # @return [String] The escaped string
13
+ def self.escape_ident(str)
14
+ return "" if str.empty?
15
+ return "\\#{str}" if str == '-' || str == '_'
16
+ out = ""
17
+ value = str.dup
18
+ out << value.slice!(0...1) if value =~ /^[-_]/
19
+ if value[0...1] =~ NMSTART
20
+ out << value.slice!(0...1)
21
+ else
22
+ out << escape_char(value.slice!(0...1))
23
+ end
24
+ out << value.gsub(/[^a-zA-Z0-9_-]/) {|c| escape_char c}
25
+ return out
26
+ end
27
+
28
+ # Escapes a single character for a CSS identifier.
29
+ #
30
+ # @param c [String] The character to escape. Should have length 1
31
+ # @return [String] The escaped character
32
+ # @private
33
+ def self.escape_char(c)
34
+ return "\\%06x" % Sass::Util.ord(c) unless c =~ /[ -\/:-~]/
35
+ return "\\#{c}"
36
+ end
37
+
38
+ # Creates a Regexp from a plain text string,
39
+ # escaping all significant characters.
40
+ #
41
+ # @param str [String] The text of the regexp
42
+ # @param flags [Fixnum] Flags for the created regular expression
43
+ # @return [Regexp]
44
+ # @private
45
+ def self.quote(str, flags = 0)
46
+ Regexp.new(Regexp.quote(str), flags)
47
+ end
48
+
49
+ H = /[0-9a-fA-F]/
50
+ NL = /\n|\r\n|\r|\f/
51
+ UNICODE = /\\#{H}{1,6}[ \t\r\n\f]?/
52
+ s = if Sass::Util.ruby1_8?
53
+ '\200-\377'
54
+ elsif Sass::Util.macruby?
55
+ '\u0080-\uD7FF\uE000-\uFFFD\U00010000-\U0010FFFF'
56
+ else
57
+ '\u{80}-\u{D7FF}\u{E000}-\u{FFFD}\u{10000}-\u{10FFFF}'
58
+ end
59
+ NONASCII = /[#{s}]/
60
+ ESCAPE = /#{UNICODE}|\\[ -~#{s}]/
61
+ NMSTART = /[_a-zA-Z]|#{NONASCII}|#{ESCAPE}/
62
+ NMCHAR = /[a-zA-Z0-9_-]|#{NONASCII}|#{ESCAPE}/
63
+ STRING1 = /\"((?:[^\n\r\f\\"]|\\#{NL}|#{ESCAPE})*)\"/
64
+ STRING2 = /\'((?:[^\n\r\f\\']|\\#{NL}|#{ESCAPE})*)\'/
65
+
66
+ IDENT = /-?#{NMSTART}#{NMCHAR}*/
67
+ NAME = /#{NMCHAR}+/
68
+ NUM = /[0-9]+|[0-9]*\.[0-9]+/
69
+ STRING = /#{STRING1}|#{STRING2}/
70
+ URLCHAR = /[#%&*-~]|#{NONASCII}|#{ESCAPE}/
71
+ URL = /(#{URLCHAR}*)/
72
+ W = /[ \t\r\n\f]*/
73
+ VARIABLE = /(\$)(#{Sass::SCSS::RX::IDENT})/
74
+
75
+ # This is more liberal than the spec's definition,
76
+ # but that definition didn't work well with the greediness rules
77
+ RANGE = /(?:#{H}|\?){1,6}/
78
+
79
+ ##
80
+
81
+ S = /[ \t\r\n\f]+/
82
+
83
+ COMMENT = /\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\//
84
+ SINGLE_LINE_COMMENT = /\/\/.*(\n[ \t]*\/\/.*)*/
85
+
86
+ CDO = quote("<!--")
87
+ CDC = quote("-->")
88
+ INCLUDES = quote("~=")
89
+ DASHMATCH = quote("|=")
90
+ PREFIXMATCH = quote("^=")
91
+ SUFFIXMATCH = quote("$=")
92
+ SUBSTRINGMATCH = quote("*=")
93
+
94
+ HASH = /##{NAME}/
95
+
96
+ IMPORTANT = /!#{W}important/i
97
+ DEFAULT = /!#{W}default/i
98
+
99
+ NUMBER = /#{NUM}(?:#{IDENT}|%)?/
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
+
123
+ IDENT_HYPHEN_INTERP = /-(#\{)/
124
+ STRING1_NOINTERP = /\"((?:[^\n\r\f\\"#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\"/
125
+ STRING2_NOINTERP = /\'((?:[^\n\r\f\\'#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\'/
126
+ STRING_NOINTERP = /#{STRING1_NOINTERP}|#{STRING2_NOINTERP}/
127
+
128
+ STATIC_COMPONENT = /#{IDENT}|#{STRING_NOINTERP}|#{HEXCOLOR}|[+-]?#{NUMBER}|\!important/i
129
+ STATIC_VALUE = /#{STATIC_COMPONENT}(\s*[\s,\/]\s*#{STATIC_COMPONENT})*([;}])/i
130
+ STATIC_SELECTOR = /(#{NMCHAR}|[ \t]|[,>+*]|[:#.]#{NMSTART}){0,50}([{])/i
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,15 @@
1
+ module Sass
2
+ module SCSS
3
+ # A mixin for subclasses of {Sass::Script::Lexer}
4
+ # that makes them usable by {SCSS::Parser} to parse SassScript.
5
+ # In particular, the lexer doesn't support `!` for a variable prefix.
6
+ module ScriptLexer
7
+ private
8
+
9
+ def variable
10
+ return [:raw, "!important"] if scan(Sass::SCSS::RX::IMPORTANT)
11
+ _variable(Sass::SCSS::RX::VARIABLE)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ module Sass
2
+ module SCSS
3
+ # A mixin for subclasses of {Sass::Script::Parser}
4
+ # that makes them usable by {SCSS::Parser} to parse SassScript.
5
+ # In particular, the parser won't raise an error
6
+ # when there's more content in the lexer once lexing is done.
7
+ # In addition, the parser doesn't support `!` for a variable prefix.
8
+ module ScriptParser
9
+ private
10
+
11
+ # @private
12
+ def lexer_class
13
+ klass = Class.new(super)
14
+ klass.send(:include, ScriptLexer)
15
+ klass
16
+ end
17
+
18
+ # Instead of raising an error when the parser is done,
19
+ # rewind the StringScanner so that it hasn't consumed the final token.
20
+ def assert_done
21
+ @lexer.unpeek!
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,54 @@
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
+ private
28
+
29
+ def moz_document_function
30
+ return unless val = tok(URI) || tok(URL_PREFIX) || tok(DOMAIN) ||
31
+ function(!:allow_var)
32
+ ss
33
+ [val]
34
+ end
35
+
36
+ def variable; nil; end
37
+ def script_value; nil; end
38
+ def interpolation; nil; end
39
+ def var_expr; nil; end
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
43
+ def use_css_import?; true; end
44
+
45
+ def special_directive(name)
46
+ return unless %w[media import charset -moz-document].include?(name)
47
+ super
48
+ end
49
+
50
+ @sass_script_parser = Class.new(Sass::Script::CssParser)
51
+ @sass_script_parser.send(:include, ScriptParser)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,452 @@
1
+ require 'sass/selector/simple'
2
+ require 'sass/selector/abstract_sequence'
3
+ require 'sass/selector/comma_sequence'
4
+ require 'sass/selector/sequence'
5
+ require 'sass/selector/simple_sequence'
6
+
7
+ module Sass
8
+ # A namespace for nodes in the parse tree for selectors.
9
+ #
10
+ # {CommaSequence} is the toplevel seelctor,
11
+ # representing a comma-separated sequence of {Sequence}s,
12
+ # such as `foo bar, baz bang`.
13
+ # {Sequence} is the next level,
14
+ # representing {SimpleSequence}s separated by combinators (e.g. descendant or child),
15
+ # such as `foo bar` or `foo > bar baz`.
16
+ # {SimpleSequence} is a sequence of selectors that all apply to a single element,
17
+ # such as `foo.bar[attr=val]`.
18
+ # Finally, {Simple} is the superclass of the simplest selectors,
19
+ # such as `.foo` or `#bar`.
20
+ module Selector
21
+ # The base used for calculating selector specificity. The spec says this
22
+ # should be "sufficiently high"; it's extremely unlikely that any single
23
+ # selector sequence will contain 1,000 simple selectors.
24
+ #
25
+ # @type [Fixnum]
26
+ SPECIFICITY_BASE = 1_000
27
+
28
+ # A parent-referencing selector (`&` in Sass).
29
+ # The function of this is to be replaced by the parent selector
30
+ # in the nested hierarchy.
31
+ class Parent < Simple
32
+ # @see Selector#to_a
33
+ def to_a
34
+ ["&"]
35
+ end
36
+
37
+ # Always raises an exception.
38
+ #
39
+ # @raise [Sass::SyntaxError] Parent selectors should be resolved before unification
40
+ # @see Selector#unify
41
+ def unify(sels)
42
+ raise Sass::SyntaxError.new("[BUG] Cannot unify parent selectors.")
43
+ end
44
+ end
45
+
46
+ # A class selector (e.g. `.foo`).
47
+ class Class < Simple
48
+ # The class name.
49
+ #
50
+ # @return [Array<String, Sass::Script::Node>]
51
+ attr_reader :name
52
+
53
+ # @param name [Array<String, Sass::Script::Node>] The class name
54
+ def initialize(name)
55
+ @name = name
56
+ end
57
+
58
+ # @see Selector#to_a
59
+ def to_a
60
+ [".", *@name]
61
+ end
62
+
63
+ # @see AbstractSequence#specificity
64
+ def specificity
65
+ SPECIFICITY_BASE
66
+ end
67
+ end
68
+
69
+ # An id selector (e.g. `#foo`).
70
+ class Id < Simple
71
+ # The id name.
72
+ #
73
+ # @return [Array<String, Sass::Script::Node>]
74
+ attr_reader :name
75
+
76
+ # @param name [Array<String, Sass::Script::Node>] The id name
77
+ def initialize(name)
78
+ @name = name
79
+ end
80
+
81
+ # @see Selector#to_a
82
+ def to_a
83
+ ["#", *@name]
84
+ end
85
+
86
+ # Returns `nil` if `sels` contains an {Id} selector
87
+ # with a different name than this one.
88
+ #
89
+ # @see Selector#unify
90
+ def unify(sels)
91
+ return if sels.any? {|sel2| sel2.is_a?(Id) && self.name != sel2.name}
92
+ super
93
+ end
94
+
95
+ # @see AbstractSequence#specificity
96
+ def specificity
97
+ SPECIFICITY_BASE**2
98
+ end
99
+ end
100
+
101
+ # A placeholder selector (e.g. `%foo`).
102
+ # This exists to be replaced via `@extend`.
103
+ # Rulesets using this selector will not be printed, but can be extended.
104
+ # Otherwise, this acts just like a class selector.
105
+ class Placeholder < Simple
106
+ # The placeholder name.
107
+ #
108
+ # @return [Array<String, Sass::Script::Node>]
109
+ attr_reader :name
110
+
111
+ # @param name [Array<String, Sass::Script::Node>] The placeholder name
112
+ def initialize(name)
113
+ @name = name
114
+ end
115
+
116
+ # @see Selector#to_a
117
+ def to_a
118
+ ["%", *@name]
119
+ end
120
+
121
+ # @see AbstractSequence#specificity
122
+ def specificity
123
+ 0
124
+ end
125
+ end
126
+
127
+ # A universal selector (`*` in CSS).
128
+ class Universal < Simple
129
+ # The selector namespace.
130
+ # `nil` means the default namespace,
131
+ # `[""]` means no namespace,
132
+ # `["*"]` means any namespace.
133
+ #
134
+ # @return [Array<String, Sass::Script::Node>, nil]
135
+ attr_reader :namespace
136
+
137
+ # @param namespace [Array<String, Sass::Script::Node>, nil] See \{#namespace}
138
+ def initialize(namespace)
139
+ @namespace = namespace
140
+ end
141
+
142
+ # @see Selector#to_a
143
+ def to_a
144
+ @namespace ? @namespace + ["|*"] : ["*"]
145
+ end
146
+
147
+ # Unification of a universal selector is somewhat complicated,
148
+ # especially when a namespace is specified.
149
+ # If there is no namespace specified
150
+ # or any namespace is specified (namespace `"*"`),
151
+ # then `sel` is returned without change
152
+ # (unless it's empty, in which case `"*"` is required).
153
+ #
154
+ # If a namespace is specified
155
+ # but `sel` does not specify a namespace,
156
+ # then the given namespace is applied to `sel`,
157
+ # either by adding this {Universal} selector
158
+ # or applying this namespace to an existing {Element} selector.
159
+ #
160
+ # If both this selector *and* `sel` specify namespaces,
161
+ # those namespaces are unified via {Simple#unify_namespaces}
162
+ # and the unified namespace is used, if possible.
163
+ #
164
+ # @todo There are lots of cases that this documentation specifies;
165
+ # make sure we thoroughly test **all of them**.
166
+ # @todo Keep track of whether a default namespace has been declared
167
+ # and handle namespace-unspecified selectors accordingly.
168
+ # @todo If any branch of a CommaSequence ends up being just `"*"`,
169
+ # then all other branches should be eliminated
170
+ #
171
+ # @see Selector#unify
172
+ def unify(sels)
173
+ name =
174
+ case sels.first
175
+ when Universal; :universal
176
+ when Element; sels.first.name
177
+ else
178
+ return [self] + sels unless namespace.nil? || namespace == ['*']
179
+ return sels unless sels.empty?
180
+ return [self]
181
+ end
182
+
183
+ ns, accept = unify_namespaces(namespace, sels.first.namespace)
184
+ return unless accept
185
+ [name == :universal ? Universal.new(ns) : Element.new(name, ns)] + sels[1..-1]
186
+ end
187
+
188
+ # @see AbstractSequence#specificity
189
+ def specificity
190
+ 0
191
+ end
192
+ end
193
+
194
+ # An element selector (e.g. `h1`).
195
+ class Element < Simple
196
+ # The element name.
197
+ #
198
+ # @return [Array<String, Sass::Script::Node>]
199
+ attr_reader :name
200
+
201
+ # The selector namespace.
202
+ # `nil` means the default namespace,
203
+ # `[""]` means no namespace,
204
+ # `["*"]` means any namespace.
205
+ #
206
+ # @return [Array<String, Sass::Script::Node>, nil]
207
+ attr_reader :namespace
208
+
209
+ # @param name [Array<String, Sass::Script::Node>] The element name
210
+ # @param namespace [Array<String, Sass::Script::Node>, nil] See \{#namespace}
211
+ def initialize(name, namespace)
212
+ @name = name
213
+ @namespace = namespace
214
+ end
215
+
216
+ # @see Selector#to_a
217
+ def to_a
218
+ @namespace ? @namespace + ["|"] + @name : @name
219
+ end
220
+
221
+ # Unification of an element selector is somewhat complicated,
222
+ # especially when a namespace is specified.
223
+ # First, if `sel` contains another {Element} with a different \{#name},
224
+ # then the selectors can't be unified and `nil` is returned.
225
+ #
226
+ # Otherwise, if `sel` doesn't specify a namespace,
227
+ # or it specifies any namespace (via `"*"`),
228
+ # then it's returned with this element selector
229
+ # (e.g. `.foo` becomes `a.foo` or `svg|a.foo`).
230
+ # Similarly, if this selector doesn't specify a namespace,
231
+ # the namespace from `sel` is used.
232
+ #
233
+ # If both this selector *and* `sel` specify namespaces,
234
+ # those namespaces are unified via {Simple#unify_namespaces}
235
+ # and the unified namespace is used, if possible.
236
+ #
237
+ # @todo There are lots of cases that this documentation specifies;
238
+ # make sure we thoroughly test **all of them**.
239
+ # @todo Keep track of whether a default namespace has been declared
240
+ # and handle namespace-unspecified selectors accordingly.
241
+ #
242
+ # @see Selector#unify
243
+ def unify(sels)
244
+ case sels.first
245
+ when Universal;
246
+ when Element; return unless name == sels.first.name
247
+ else return [self] + sels
248
+ end
249
+
250
+ ns, accept = unify_namespaces(namespace, sels.first.namespace)
251
+ return unless accept
252
+ [Element.new(name, ns)] + sels[1..-1]
253
+ end
254
+
255
+ # @see AbstractSequence#specificity
256
+ def specificity
257
+ 1
258
+ end
259
+ end
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
+
287
+ # An attribute selector (e.g. `[href^="http://"]`).
288
+ class Attribute < Simple
289
+ # The attribute name.
290
+ #
291
+ # @return [Array<String, Sass::Script::Node>]
292
+ attr_reader :name
293
+
294
+ # The attribute namespace.
295
+ # `nil` means the default namespace,
296
+ # `[""]` means no namespace,
297
+ # `["*"]` means any namespace.
298
+ #
299
+ # @return [Array<String, Sass::Script::Node>, nil]
300
+ attr_reader :namespace
301
+
302
+ # The matching operator, e.g. `"="` or `"^="`.
303
+ #
304
+ # @return [String]
305
+ attr_reader :operator
306
+
307
+ # The right-hand side of the operator.
308
+ #
309
+ # @return [Array<String, Sass::Script::Node>]
310
+ attr_reader :value
311
+
312
+ # Flags for the attribute selector (e.g. `i`).
313
+ #
314
+ # @return [Array<String, Sass::Script::Node>]
315
+ attr_reader :flags
316
+
317
+ # @param name [Array<String, Sass::Script::Node>] The attribute name
318
+ # @param namespace [Array<String, Sass::Script::Node>, nil] See \{#namespace}
319
+ # @param operator [String] The matching operator, e.g. `"="` or `"^="`
320
+ # @param value [Array<String, Sass::Script::Node>] See \{#value}
321
+ # @param value [Array<String, Sass::Script::Node>] See \{#flags}
322
+ def initialize(name, namespace, operator, value, flags)
323
+ @name = name
324
+ @namespace = namespace
325
+ @operator = operator
326
+ @value = value
327
+ @flags = flags
328
+ end
329
+
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
337
+ res << "]"
338
+ end
339
+
340
+ # @see AbstractSequence#specificity
341
+ def specificity
342
+ SPECIFICITY_BASE
343
+ end
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
451
+ end
452
+ end