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/less.rb DELETED
@@ -1,382 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'less'
4
-
5
- module Less
6
- # This is the class that Treetop defines for parsing Less files.
7
- # Since not everything gets parsed into the AST but is instead resolved at parse-time,
8
- # we need to override some of it so that it can be converted into Sass.
9
- module StyleSheet
10
- # Selector mixins that don't have arguments.
11
- # This depends only on the syntax at the call site;
12
- # if it doesn't use parens, it hits this production,
13
- # regardless of whether the mixin being called has arguments or not.
14
- module Mixin4
15
- def build_with_sass(env)
16
- selectors.build(env, :mixin).each do |path|
17
- el = path.inject(env.root) do |current, node|
18
- current.descend(node.selector, node) or raise MixinNameError, "#{selectors.text_value} in #{env}"
19
- end
20
- if el.is_a?(Node::Mixin::Def)
21
- # Calling a mixin with arguments, which gets compiled to a Sass mixin
22
- env << Node::Mixin::Call.new(el, [], env)
23
- else
24
- # Calling a mixin without arguments, which gets compiled to @extend
25
- sel = selector_str(path)
26
- base = selector_str(selector_base(path))
27
- if base == sel
28
- env << Node::SassNode.new(Sass::Tree::ExtendNode.new([sel]))
29
- else
30
- Sass::Util.sass_warn <<WARNING
31
- WARNING: Sass doesn't support mixing in selector sequences.
32
- Replacing "#{sel}" with "@extend #{base}"
33
- WARNING
34
- env << Node::SassNode.new(Sass::Tree::CommentNode.new("// #{sel};", true))
35
- env << Node::SassNode.new(Sass::Tree::ExtendNode.new([base]))
36
- end
37
- end
38
- end
39
- end
40
- alias_method :build_without_sass, :build
41
- alias_method :build, :build_with_sass
42
-
43
- def selector_base(path)
44
- el, i = Sass::Util.enum_with_index(path).to_a.reverse.find {|e, i| e.selector !~ /^:{1,2}$/} ||
45
- [path.first, 0]
46
- sel = (el.selector =~ /^:{0,2}$/ ? el.selector : "")
47
- [Node::Element.new(el.name, sel)] + path[i+1..-1]
48
- end
49
-
50
- def selector_str(path)
51
- path.map {|e| e.sass_selector_str}.join(' ').gsub(' :', ':')
52
- end
53
- end
54
-
55
- # Property and variable declarations.
56
- # We want to keep track of the line number
57
- # so we don't space out the variables too much in the generated Sass.
58
- module Declaration3
59
- def build_with_sass(env)
60
- build_without_sass(env)
61
- env.rules.last.src_line = input.line_of(interval.first)
62
- end
63
- alias_method :build_without_sass, :build
64
- alias_method :build, :build_with_sass
65
- end
66
-
67
- # Comma-separated selectors.
68
- # Less breaks these into completely separate nodes.
69
- # Since we don't want this duplication in the Sass,
70
- # we modify the production to keep track of the original group
71
- # so we can reconstruct it later on.
72
- module Selectors2
73
- def build_with_sass(env, method)
74
- arr = build_without_sass(env, method)
75
- return arr if method == :mixin
76
- rarr = arr.map {|e| e.top(env)}
77
- rarr.each {|e| e.group = rarr}
78
- arr
79
- end
80
- alias_method :build_without_sass, :build
81
- alias_method :build, :build_with_sass
82
- end
83
-
84
- # Attribute accessors.
85
- # Sass just flat-out doesn't support these,
86
- # so we print a warning to that effect and compile them to comments.
87
- module Accessor1
88
- def build(env)
89
- Sass::Util.sass_warn <<WARNING
90
- WARNING: Sass doesn't support attribute accessors.
91
- Ignoring #{text_value}
92
- WARNING
93
- Node::Anonymous.new("/* #{text_value} */")
94
- end
95
- end
96
-
97
- # @import statements.
98
- # Less handles these during parse-time,
99
- # so we want to wrap them up as a node in the tree.
100
- # We also include the nodes, though,
101
- # since we want to have access to the mixins
102
- # so we can tell if they take arguments or not.
103
- # The included nodes are hidden so they don't appear in the output.
104
- module Import1
105
- def build_with_sass(env)
106
- line = input.line_of(interval.first)
107
- import = Sass::Tree::ImportNode.new(url.value.gsub(/\.less$/, ''))
108
- import.line = input.line_of(interval.first)
109
- env << Node::SassNode.new(import)
110
- old_rules = env.rules.dup
111
- build_without_sass env
112
- (env.rules - old_rules).each {|r| r.hide_in_sass = true}
113
- rescue ImportError => e
114
- raise Sass::SyntaxError.new("File to import #{url.text_value} not found or unreadable", :line => line)
115
- end
116
- alias_method :build_without_sass, :build
117
- alias_method :build, :build_with_sass
118
- end
119
-
120
- # The IE-specific `alpha(opacity=@var)`.
121
- # Less manually resolves the variable here at parse-time.
122
- # We want to keep the variable around,
123
- # so we compile this to a function.
124
- # Less doesn't actually have an `=` operator,
125
- # but that's okay since it's just getting compiled to Sass anyway.
126
- module Entity::Alpha1
127
- def build(env)
128
- Node::Function.new("alpha",
129
- [Node::Expression.new([
130
- Node::Keyword.new("opacity"),
131
- Node::Operator.new("="),
132
- variable.build])])
133
- end
134
- end
135
- end
136
-
137
- # The Less AST classes for the document,
138
- # including both stylesheet-level nodes and expression-level nodes.
139
- # The main purpose of overriding these is to add `#to_sass_tree` functions
140
- # for converting to Sass.
141
- module Node
142
- module Entity
143
- attr_accessor :hide_in_sass
144
- attr_accessor :src_line
145
- end
146
-
147
- class Element
148
- attr_accessor :group
149
-
150
- def top(env)
151
- return self if parent.equal?(env)
152
- return parent.top(env)
153
- end
154
-
155
- def to_sass_tree
156
- if root?
157
- root = Sass::Tree::RootNode.new("")
158
- rules.each {|r| root << r.to_sass_tree}
159
- return root
160
- end
161
- return if hide_in_sass
162
- return if !self.equal?(group.first)
163
-
164
- last_el = nil
165
- sel = group.map do |el|
166
- comma_sel = []
167
- loop do
168
- comma_sel << el.sass_selector_str
169
- break unless el.rules.size == 1 && el.rules.first.is_a?(Element)
170
- el = el.rules.first
171
- end
172
- last_el = el
173
- comma_sel = comma_sel.join(' ').gsub(' :', ':')
174
- comma_sel.gsub!(/^:/, '&:') unless parent.root?
175
- comma_sel
176
- end.join(', ')
177
-
178
- rule = Sass::Tree::RuleNode.new([sel])
179
- last_el.rules.each {|r| rule << r.to_sass_tree}
180
- return rule
181
- end
182
-
183
- def sass_selector_str
184
- case @selector
185
- when /[+>~]/; "#{@selector} #{@name}"
186
- else @selector + @name
187
- end
188
- end
189
- end
190
-
191
- module Mixin
192
- class Call
193
- def to_sass_tree
194
- return if hide_in_sass
195
- Sass::Tree::MixinNode.new(@mixin.name.gsub(/^\./, ''), @params.map {|v| v.to_sass_tree}, {})
196
- end
197
- end
198
-
199
- class Def
200
- def to_sass_tree
201
- return if hide_in_sass
202
- mixin = Sass::Tree::MixinDefNode.new(name, @params.map do |v|
203
- v.value.flatten!
204
- [Sass::Script::Variable.new(v), v.value.to_sass_tree]
205
- end)
206
- rules.each {|r| mixin << r.to_sass_tree}
207
- mixin
208
- end
209
- end
210
- end
211
-
212
- class SassNode
213
- include Entity
214
-
215
- def initialize(node)
216
- @node = node
217
- end
218
-
219
- def to_sass_tree
220
- return if hide_in_sass
221
- @node
222
- end
223
- end
224
-
225
- class Property
226
- def to_sass_tree
227
- return if hide_in_sass
228
- Sass::Tree::PropNode.new([self], @value.to_sass_tree, false, :new)
229
- end
230
- end
231
-
232
- class Expression
233
- def to_sass_tree
234
- if first.is_a?(Array)
235
- val = map {|e| _to_sass_tree(e)}.inject(nil) do |e, i|
236
- next i unless e
237
- Sass::Script::Operation.new(e, i, :comma)
238
- end
239
- else
240
- val = _to_sass_tree(self)
241
- end
242
- val.options = {}
243
- val
244
- end
245
-
246
- private
247
-
248
- LESS_TO_SASS_OPERATORS = {"-" => :minus, "+" => :plus, "*" => :times, "/" => :div, "=" => :single_eq}
249
-
250
- def _to_sass_tree(arr)
251
- e, rest = _to_sass_tree_plus_minus_eq(arr)
252
- until rest.empty?
253
- e2, rest = _to_sass_tree_plus_minus_eq(rest)
254
- e = Sass::Script::Operation.new(e, e2, :space)
255
- end
256
- return e
257
- end
258
-
259
- def _to_sass_tree_plus_minus_eq(arr)
260
- e, rest = _to_sass_tree_times_div(arr)
261
- while rest[0] && rest[0].is_a?(Operator) && %w[+ - =].include?(rest[0])
262
- op = LESS_TO_SASS_OPERATORS[rest[0]]
263
- e2, rest = _to_sass_tree_times_div(rest[1..-1])
264
- e = Sass::Script::Operation.new(e, e2, op)
265
- end
266
- return e, rest
267
- end
268
-
269
- def _to_sass_tree_times_div(arr)
270
- e, rest = _to_sass_tree_unary(arr)
271
- while rest[0] && rest[0].is_a?(Operator) && %w[* /].include?(rest[0])
272
- op = LESS_TO_SASS_OPERATORS[rest[0]]
273
- e2, rest = _to_sass_tree_unary(rest[1..-1])
274
- e = Sass::Script::Operation.new(e, e2, op)
275
- end
276
- return e, rest
277
- end
278
-
279
- def _to_sass_tree_unary(arr)
280
- if arr[0] == "-"
281
- first, rest = _sass_split(arr[1..-1])
282
- return Sass::Script::UnaryOperation.new(first, :minus), rest
283
- else
284
- return _sass_split(arr[0..-1])
285
- end
286
- end
287
-
288
- def _sass_split(arr)
289
- return arr[0].to_sass_tree, arr[1..-1] unless arr[0] == "("
290
- parens = 1
291
- i = arr[1..-1].each_with_index do |e, i|
292
- parens += 1 if e == "("
293
- parens -= 1 if e == ")"
294
- break i if parens == 0
295
- end
296
-
297
- return _to_sass_tree(arr[1...i+1]), arr[i+2..-1]
298
- end
299
- end
300
-
301
- class Color
302
- def to_sass_tree
303
- Sass::Script::Color.new(:red => r, :green => g, :blue => b, :alpha => a)
304
- end
305
- end
306
-
307
- class Number
308
- def to_sass_tree
309
- Sass::Script::Number.new(self, [self.unit])
310
- end
311
- end
312
-
313
- class Variable
314
- def to_sass_tree
315
- if @declaration
316
- return if hide_in_sass
317
- node = Sass::Tree::VariableNode.new(self, @value.to_sass_tree, false)
318
- node.line = self.src_line
319
- node
320
- else
321
- Sass::Script::Variable.new(self)
322
- end
323
- end
324
- end
325
-
326
- class Function
327
- def to_sass_tree
328
- Sass::Script::Funcall.new(self, @args.map {|a| a.to_sass_tree}, {})
329
- end
330
- end
331
-
332
- class Keyword
333
- def to_sass_tree
334
- Sass::Script::String.new(self)
335
- end
336
- end
337
-
338
- class Anonymous
339
- def to_sass_tree
340
- Sass::Script::String.new(self)
341
- end
342
- end
343
-
344
- class Quoted
345
- def to_sass_tree
346
- Sass::Script::String.new(self, true)
347
- end
348
- end
349
-
350
- class FontFamily
351
- def to_sass_tree
352
- @family.map {|f| f.to_sass_tree}.inject(nil) do |e, f|
353
- next f unless e
354
- Sass::Script::Operation.new(e, f, :comma)
355
- end
356
- end
357
- end
358
- end
359
-
360
- # The entry point to Less.
361
- # By default Less doesn't preserve the filename of the file being parsed,
362
- # which is unpleasant for error reporting.
363
- # Our monkeypatch keeps it around.
364
- class Engine
365
- def initialize_with_sass(obj, opts = {})
366
- initialize_without_sass(obj, opts)
367
- @filename = obj.path if obj.is_a?(File)
368
- end
369
- alias_method :initialize_without_sass, :initialize
370
- alias_method :initialize, :initialize_with_sass
371
-
372
- def parse_with_sass
373
- parse_without_sass
374
- rescue Sass::SyntaxError => e
375
- e.modify_backtrace(:filename => @filename)
376
- raise e
377
- end
378
- alias_method :parse_without_sass, :parse
379
- alias_method :parse, :parse_with_sass
380
- alias_method :to_tree, :parse
381
- end
382
- end
@@ -1,18 +0,0 @@
1
- require 'sass/script/literal'
2
-
3
- module Sass::Script
4
- # A SassScript object representing a boolean (true or false) value.
5
- class Bool < Literal
6
- # The Ruby value of the boolean.
7
- #
8
- # @return [Boolean]
9
- attr_reader :value
10
- alias_method :to_bool, :value
11
-
12
- # @return [String] "true" or "false"
13
- def to_s(opts = {})
14
- @value.to_s
15
- end
16
- alias_method :to_sass, :to_s
17
- end
18
- end
@@ -1,162 +0,0 @@
1
- require 'sass/script/functions'
2
-
3
- module Sass
4
- module Script
5
- # A SassScript parse node representing a function call.
6
- #
7
- # A function call either calls one of the functions in {Script::Functions},
8
- # or if no function with the given name exists
9
- # it returns a string representation of the function call.
10
- class Funcall < Node
11
- # The name of the function.
12
- #
13
- # @return [String]
14
- attr_reader :name
15
-
16
- # The arguments to the function.
17
- #
18
- # @return [Array<Script::Node>]
19
- attr_reader :args
20
-
21
- # The keyword arguments to the function.
22
- #
23
- # @return [{String => Script::Node}]
24
- attr_reader :keywords
25
-
26
- # @param name [String] See \{#name}
27
- # @param args [Array<Script::Node>] See \{#args}
28
- # @param keywords [{String => Script::Node}] See \{#keywords}
29
- def initialize(name, args, keywords)
30
- @name = name
31
- @args = args
32
- @keywords = keywords
33
- super()
34
- end
35
-
36
- # @return [String] A string representation of the function call
37
- def inspect
38
- args = @args.map {|a| a.inspect}.join(', ')
39
- keywords = @keywords.sort_by {|k, v| k}.
40
- map {|k, v| "$#{k}: #{v.inspect}"}.join(', ')
41
- "#{name}(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords})"
42
- end
43
-
44
- # @see Node#to_sass
45
- def to_sass(opts = {})
46
- args = @args.map {|a| a.to_sass(opts)}.join(', ')
47
- keywords = @keywords.sort_by {|k, v| k}.
48
- map {|k, v| "$#{dasherize(k, opts)}: #{v.to_sass(opts)}"}.join(', ')
49
- "#{dasherize(name, opts)}(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords})"
50
- end
51
-
52
- # Returns the arguments to the function.
53
- #
54
- # @return [Array<Node>]
55
- # @see Node#children
56
- def children
57
- @args + @keywords.values
58
- end
59
-
60
- protected
61
-
62
- # Evaluates the function call.
63
- #
64
- # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
65
- # @return [Literal] The SassScript object that is the value of the function call
66
- # @raise [Sass::SyntaxError] if the function call raises an ArgumentError
67
- def _perform(environment)
68
- args = @args.map {|a| a.perform(environment)}
69
- if fn = environment.function(@name)
70
- keywords = Sass::Util.map_hash(@keywords) {|k, v| [k, v.perform(environment)]}
71
- return perform_sass_fn(fn, args, keywords)
72
- end
73
-
74
- ruby_name = @name.tr('-', '_')
75
- args = construct_ruby_args(ruby_name, args, environment)
76
-
77
- unless Functions.callable?(ruby_name)
78
- opts(to_literal(args))
79
- else
80
- opts(Functions::EvaluationContext.new(environment.options).send(ruby_name, *args))
81
- end
82
- rescue ArgumentError => e
83
- raise e unless e.backtrace.any? {|t| t =~ /:in `(block in )?(#{name}|perform)'$/}
84
- raise Sass::SyntaxError.new("#{e.message} for `#{name}'")
85
- end
86
-
87
- # This method is factored out from `_perform` so that compass can override
88
- # it with a cross-browser implementation for functions that require vendor prefixes
89
- # in the generated css.
90
- def to_literal(args)
91
- Script::String.new("#{name}(#{args.join(', ')})")
92
- end
93
-
94
- private
95
-
96
- def construct_ruby_args(name, args, environment)
97
- unless signature = Functions.signature(name.to_sym, args.size, @keywords.size)
98
- return args if keywords.empty?
99
- raise Sass::SyntaxError.new("Function #{name} doesn't support keyword arguments")
100
- end
101
- keywords = Sass::Util.map_hash(@keywords) {|k, v| [k, v.perform(environment)]}
102
-
103
- # If the user passes more non-keyword args than the function expects,
104
- # but it does expect keyword args, Ruby's arg handling won't raise an error.
105
- # Since we don't want to make functions think about this,
106
- # we'll handle it for them here.
107
- if signature.var_kwargs && !signature.var_args && args.size > signature.args.size
108
- raise Sass::SyntaxError.new(
109
- "#{args[signature.args.size].inspect} is not a keyword argument for `#{name}'")
110
- elsif keywords.empty?
111
- return args
112
- end
113
-
114
- args = args + signature.args[args.size..-1].map do |argname|
115
- if keywords.has_key?(argname)
116
- keywords.delete(argname)
117
- else
118
- raise Sass::SyntaxError.new("Function #{name} requires an argument named $#{argname}")
119
- end
120
- end
121
-
122
- if keywords.size > 0
123
- if signature.var_kwargs
124
- args << keywords
125
- else
126
- raise Sass::SyntaxError.new("Function #{name} doesn't take an argument named $#{keywords.keys.sort.first}")
127
- end
128
- end
129
-
130
- args
131
- end
132
-
133
- def perform_sass_fn(function, args, keywords)
134
- # TODO: merge with mixin arg evaluation?
135
- keywords.each do |name, value|
136
- # TODO: Make this fast
137
- unless function.args.find {|(var, default)| var.underscored_name == name}
138
- raise Sass::SyntaxError.new("Function #{@name} doesn't have an argument named $#{name}")
139
- end
140
- end
141
-
142
- if args.size > function.args.size
143
- raise ArgumentError.new("Wrong number of arguments (#{args.size} for #{function.args.size})")
144
- end
145
-
146
- environment = function.args.zip(args).
147
- inject(Sass::Environment.new(function.environment)) do |env, ((var, default), value)|
148
- env.set_local_var(var.name,
149
- value || keywords[var.underscored_name] || (default && default.perform(env)))
150
- raise Sass::SyntaxError.new("Function #{@name} is missing parameter #{var.inspect}.") unless env.var(var.name)
151
- env
152
- end
153
-
154
- val = catch :_sass_return do
155
- function.tree.each {|c| Sass::Tree::Visitors::Perform.visit(c, environment)}
156
- raise Sass::SyntaxError.new("Function #{@name} finished without @return")
157
- end
158
- val
159
- end
160
- end
161
- end
162
- end
@@ -1,76 +0,0 @@
1
- module Sass::Script
2
- # A SassScript object representing a CSS list.
3
- # This includes both comma-separated lists and space-separated lists.
4
- class List < Literal
5
- # The Ruby array containing the contents of the list.
6
- #
7
- # @return [Array<Literal>]
8
- attr_reader :value
9
- alias_method :children, :value
10
- alias_method :to_a, :value
11
-
12
- # The operator separating the values of the list.
13
- # Either `:comma` or `:space`.
14
- #
15
- # @return [Symbol]
16
- attr_reader :separator
17
-
18
- # Creates a new list.
19
- #
20
- # @param value [Array<Literal>] See \{#value}
21
- # @param separator [String] See \{#separator}
22
- def initialize(value, separator)
23
- super(value)
24
- @separator = separator
25
- end
26
-
27
- # @see Node#eq
28
- def eq(other)
29
- Sass::Script::Bool.new(
30
- self.class == other.class && self.value == other.value &&
31
- self.separator == other.separator)
32
- end
33
-
34
- # @see Node#to_s
35
- def to_s(opts = {})
36
- raise Sass::SyntaxError.new("() isn't a valid CSS value.") if value.empty?
37
- return value.reject {|e| e.is_a?(List) && e.value.empty?}.map {|e| e.to_s(opts)}.join(sep_str)
38
- end
39
-
40
- # @see Node#to_sass
41
- def to_sass(opts = {})
42
- precedence = Sass::Script::Parser.precedence_of(separator)
43
- value.map do |v|
44
- if v.is_a?(List) && Sass::Script::Parser.precedence_of(v.separator) <= precedence
45
- "(#{v.to_sass(opts)})"
46
- else
47
- v.to_sass(opts)
48
- end
49
- end.join(sep_str(nil))
50
- end
51
-
52
- # @see Node#inspect
53
- def inspect
54
- "(#{to_sass})"
55
- end
56
-
57
- protected
58
-
59
- # @see Node#_perform
60
- def _perform(environment)
61
- list = Sass::Script::List.new(
62
- value.map {|e| e.perform(environment)},
63
- separator)
64
- list.options = self.options
65
- list
66
- end
67
-
68
- private
69
-
70
- def sep_str(opts = self.options)
71
- return ' ' if separator == :space
72
- return ',' if opts && opts[:style] == :compressed
73
- return ', '
74
- end
75
- end
76
- end