oreorenasass 3.4.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 (268) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +11 -0
  3. data/CONTRIBUTING +3 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +221 -0
  6. data/Rakefile +370 -0
  7. data/VERSION +1 -0
  8. data/VERSION_NAME +1 -0
  9. data/bin/sass +13 -0
  10. data/bin/sass-convert +12 -0
  11. data/bin/scss +13 -0
  12. data/extra/update_watch.rb +13 -0
  13. data/init.rb +18 -0
  14. data/lib/sass/cache_stores/base.rb +88 -0
  15. data/lib/sass/cache_stores/chain.rb +34 -0
  16. data/lib/sass/cache_stores/filesystem.rb +60 -0
  17. data/lib/sass/cache_stores/memory.rb +47 -0
  18. data/lib/sass/cache_stores/null.rb +25 -0
  19. data/lib/sass/cache_stores.rb +15 -0
  20. data/lib/sass/callbacks.rb +67 -0
  21. data/lib/sass/css.rb +407 -0
  22. data/lib/sass/engine.rb +1181 -0
  23. data/lib/sass/environment.rb +191 -0
  24. data/lib/sass/error.rb +198 -0
  25. data/lib/sass/exec/base.rb +187 -0
  26. data/lib/sass/exec/sass_convert.rb +264 -0
  27. data/lib/sass/exec/sass_scss.rb +424 -0
  28. data/lib/sass/exec.rb +9 -0
  29. data/lib/sass/features.rb +47 -0
  30. data/lib/sass/importers/base.rb +182 -0
  31. data/lib/sass/importers/filesystem.rb +211 -0
  32. data/lib/sass/importers.rb +22 -0
  33. data/lib/sass/logger/base.rb +30 -0
  34. data/lib/sass/logger/log_level.rb +45 -0
  35. data/lib/sass/logger.rb +12 -0
  36. data/lib/sass/media.rb +210 -0
  37. data/lib/sass/plugin/compiler.rb +565 -0
  38. data/lib/sass/plugin/configuration.rb +118 -0
  39. data/lib/sass/plugin/generic.rb +15 -0
  40. data/lib/sass/plugin/merb.rb +48 -0
  41. data/lib/sass/plugin/rack.rb +60 -0
  42. data/lib/sass/plugin/rails.rb +47 -0
  43. data/lib/sass/plugin/staleness_checker.rb +199 -0
  44. data/lib/sass/plugin.rb +133 -0
  45. data/lib/sass/railtie.rb +10 -0
  46. data/lib/sass/repl.rb +57 -0
  47. data/lib/sass/root.rb +7 -0
  48. data/lib/sass/script/css_lexer.rb +33 -0
  49. data/lib/sass/script/css_parser.rb +34 -0
  50. data/lib/sass/script/functions.rb +2626 -0
  51. data/lib/sass/script/lexer.rb +449 -0
  52. data/lib/sass/script/parser.rb +637 -0
  53. data/lib/sass/script/tree/funcall.rb +306 -0
  54. data/lib/sass/script/tree/interpolation.rb +118 -0
  55. data/lib/sass/script/tree/list_literal.rb +77 -0
  56. data/lib/sass/script/tree/literal.rb +45 -0
  57. data/lib/sass/script/tree/map_literal.rb +64 -0
  58. data/lib/sass/script/tree/node.rb +109 -0
  59. data/lib/sass/script/tree/operation.rb +103 -0
  60. data/lib/sass/script/tree/selector.rb +26 -0
  61. data/lib/sass/script/tree/string_interpolation.rb +104 -0
  62. data/lib/sass/script/tree/unary_operation.rb +69 -0
  63. data/lib/sass/script/tree/variable.rb +57 -0
  64. data/lib/sass/script/tree.rb +16 -0
  65. data/lib/sass/script/value/arg_list.rb +36 -0
  66. data/lib/sass/script/value/base.rb +240 -0
  67. data/lib/sass/script/value/bool.rb +35 -0
  68. data/lib/sass/script/value/color.rb +680 -0
  69. data/lib/sass/script/value/helpers.rb +262 -0
  70. data/lib/sass/script/value/list.rb +113 -0
  71. data/lib/sass/script/value/map.rb +70 -0
  72. data/lib/sass/script/value/null.rb +44 -0
  73. data/lib/sass/script/value/number.rb +530 -0
  74. data/lib/sass/script/value/string.rb +97 -0
  75. data/lib/sass/script/value.rb +11 -0
  76. data/lib/sass/script.rb +66 -0
  77. data/lib/sass/scss/css_parser.rb +42 -0
  78. data/lib/sass/scss/parser.rb +1209 -0
  79. data/lib/sass/scss/rx.rb +141 -0
  80. data/lib/sass/scss/script_lexer.rb +15 -0
  81. data/lib/sass/scss/script_parser.rb +25 -0
  82. data/lib/sass/scss/static_parser.rb +368 -0
  83. data/lib/sass/scss.rb +16 -0
  84. data/lib/sass/selector/abstract_sequence.rb +109 -0
  85. data/lib/sass/selector/comma_sequence.rb +175 -0
  86. data/lib/sass/selector/pseudo.rb +256 -0
  87. data/lib/sass/selector/sequence.rb +600 -0
  88. data/lib/sass/selector/simple.rb +117 -0
  89. data/lib/sass/selector/simple_sequence.rb +325 -0
  90. data/lib/sass/selector.rb +326 -0
  91. data/lib/sass/shared.rb +76 -0
  92. data/lib/sass/source/map.rb +210 -0
  93. data/lib/sass/source/position.rb +39 -0
  94. data/lib/sass/source/range.rb +41 -0
  95. data/lib/sass/stack.rb +120 -0
  96. data/lib/sass/supports.rb +227 -0
  97. data/lib/sass/tree/at_root_node.rb +83 -0
  98. data/lib/sass/tree/charset_node.rb +22 -0
  99. data/lib/sass/tree/comment_node.rb +82 -0
  100. data/lib/sass/tree/content_node.rb +9 -0
  101. data/lib/sass/tree/css_import_node.rb +60 -0
  102. data/lib/sass/tree/debug_node.rb +18 -0
  103. data/lib/sass/tree/directive_node.rb +59 -0
  104. data/lib/sass/tree/each_node.rb +24 -0
  105. data/lib/sass/tree/error_node.rb +18 -0
  106. data/lib/sass/tree/extend_node.rb +43 -0
  107. data/lib/sass/tree/for_node.rb +36 -0
  108. data/lib/sass/tree/function_node.rb +39 -0
  109. data/lib/sass/tree/if_node.rb +52 -0
  110. data/lib/sass/tree/import_node.rb +74 -0
  111. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  112. data/lib/sass/tree/media_node.rb +48 -0
  113. data/lib/sass/tree/mixin_def_node.rb +38 -0
  114. data/lib/sass/tree/mixin_node.rb +52 -0
  115. data/lib/sass/tree/node.rb +238 -0
  116. data/lib/sass/tree/prop_node.rb +171 -0
  117. data/lib/sass/tree/return_node.rb +19 -0
  118. data/lib/sass/tree/root_node.rb +44 -0
  119. data/lib/sass/tree/rule_node.rb +145 -0
  120. data/lib/sass/tree/supports_node.rb +38 -0
  121. data/lib/sass/tree/trace_node.rb +33 -0
  122. data/lib/sass/tree/variable_node.rb +36 -0
  123. data/lib/sass/tree/visitors/base.rb +72 -0
  124. data/lib/sass/tree/visitors/check_nesting.rb +177 -0
  125. data/lib/sass/tree/visitors/convert.rb +334 -0
  126. data/lib/sass/tree/visitors/cssize.rb +369 -0
  127. data/lib/sass/tree/visitors/deep_copy.rb +107 -0
  128. data/lib/sass/tree/visitors/extend.rb +68 -0
  129. data/lib/sass/tree/visitors/perform.rb +539 -0
  130. data/lib/sass/tree/visitors/set_options.rb +139 -0
  131. data/lib/sass/tree/visitors/to_css.rb +381 -0
  132. data/lib/sass/tree/warn_node.rb +18 -0
  133. data/lib/sass/tree/while_node.rb +18 -0
  134. data/lib/sass/util/cross_platform_random.rb +19 -0
  135. data/lib/sass/util/multibyte_string_scanner.rb +157 -0
  136. data/lib/sass/util/normalized_map.rb +130 -0
  137. data/lib/sass/util/ordered_hash.rb +192 -0
  138. data/lib/sass/util/subset_map.rb +110 -0
  139. data/lib/sass/util/test.rb +9 -0
  140. data/lib/sass/util.rb +1318 -0
  141. data/lib/sass/version.rb +124 -0
  142. data/lib/sass.rb +102 -0
  143. data/rails/init.rb +1 -0
  144. data/test/sass/cache_test.rb +131 -0
  145. data/test/sass/callbacks_test.rb +61 -0
  146. data/test/sass/compiler_test.rb +232 -0
  147. data/test/sass/conversion_test.rb +2054 -0
  148. data/test/sass/css2sass_test.rb +477 -0
  149. data/test/sass/data/hsl-rgb.txt +319 -0
  150. data/test/sass/encoding_test.rb +219 -0
  151. data/test/sass/engine_test.rb +3301 -0
  152. data/test/sass/exec_test.rb +86 -0
  153. data/test/sass/extend_test.rb +1661 -0
  154. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  155. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  156. data/test/sass/functions_test.rb +1926 -0
  157. data/test/sass/importer_test.rb +412 -0
  158. data/test/sass/logger_test.rb +58 -0
  159. data/test/sass/mock_importer.rb +49 -0
  160. data/test/sass/more_results/more1.css +9 -0
  161. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  162. data/test/sass/more_results/more_import.css +29 -0
  163. data/test/sass/more_templates/_more_partial.sass +2 -0
  164. data/test/sass/more_templates/more1.sass +23 -0
  165. data/test/sass/more_templates/more_import.sass +11 -0
  166. data/test/sass/plugin_test.rb +554 -0
  167. data/test/sass/results/alt.css +4 -0
  168. data/test/sass/results/basic.css +9 -0
  169. data/test/sass/results/cached_import_option.css +3 -0
  170. data/test/sass/results/compact.css +5 -0
  171. data/test/sass/results/complex.css +86 -0
  172. data/test/sass/results/compressed.css +1 -0
  173. data/test/sass/results/expanded.css +19 -0
  174. data/test/sass/results/filename_fn.css +3 -0
  175. data/test/sass/results/if.css +3 -0
  176. data/test/sass/results/import.css +31 -0
  177. data/test/sass/results/import_charset.css +5 -0
  178. data/test/sass/results/import_charset_1_8.css +5 -0
  179. data/test/sass/results/import_charset_ibm866.css +5 -0
  180. data/test/sass/results/import_content.css +1 -0
  181. data/test/sass/results/line_numbers.css +49 -0
  182. data/test/sass/results/mixins.css +95 -0
  183. data/test/sass/results/multiline.css +24 -0
  184. data/test/sass/results/nested.css +22 -0
  185. data/test/sass/results/options.css +1 -0
  186. data/test/sass/results/parent_ref.css +13 -0
  187. data/test/sass/results/script.css +16 -0
  188. data/test/sass/results/scss_import.css +31 -0
  189. data/test/sass/results/scss_importee.css +2 -0
  190. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  191. data/test/sass/results/subdir/subdir.css +3 -0
  192. data/test/sass/results/units.css +11 -0
  193. data/test/sass/results/warn.css +0 -0
  194. data/test/sass/results/warn_imported.css +0 -0
  195. data/test/sass/script_conversion_test.rb +328 -0
  196. data/test/sass/script_test.rb +1054 -0
  197. data/test/sass/scss/css_test.rb +1215 -0
  198. data/test/sass/scss/rx_test.rb +156 -0
  199. data/test/sass/scss/scss_test.rb +3900 -0
  200. data/test/sass/scss/test_helper.rb +37 -0
  201. data/test/sass/source_map_test.rb +977 -0
  202. data/test/sass/superselector_test.rb +191 -0
  203. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  204. data/test/sass/templates/_double_import_loop2.sass +1 -0
  205. data/test/sass/templates/_filename_fn_import.scss +11 -0
  206. data/test/sass/templates/_imported_charset_ibm866.sass +4 -0
  207. data/test/sass/templates/_imported_charset_utf8.sass +4 -0
  208. data/test/sass/templates/_imported_content.sass +3 -0
  209. data/test/sass/templates/_partial.sass +2 -0
  210. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  211. data/test/sass/templates/alt.sass +16 -0
  212. data/test/sass/templates/basic.sass +23 -0
  213. data/test/sass/templates/bork1.sass +2 -0
  214. data/test/sass/templates/bork2.sass +2 -0
  215. data/test/sass/templates/bork3.sass +2 -0
  216. data/test/sass/templates/bork4.sass +2 -0
  217. data/test/sass/templates/bork5.sass +3 -0
  218. data/test/sass/templates/cached_import_option.scss +3 -0
  219. data/test/sass/templates/compact.sass +17 -0
  220. data/test/sass/templates/complex.sass +305 -0
  221. data/test/sass/templates/compressed.sass +15 -0
  222. data/test/sass/templates/double_import_loop1.sass +1 -0
  223. data/test/sass/templates/expanded.sass +17 -0
  224. data/test/sass/templates/filename_fn.scss +18 -0
  225. data/test/sass/templates/if.sass +11 -0
  226. data/test/sass/templates/import.sass +12 -0
  227. data/test/sass/templates/import_charset.sass +9 -0
  228. data/test/sass/templates/import_charset_1_8.sass +6 -0
  229. data/test/sass/templates/import_charset_ibm866.sass +11 -0
  230. data/test/sass/templates/import_content.sass +4 -0
  231. data/test/sass/templates/importee.less +2 -0
  232. data/test/sass/templates/importee.sass +19 -0
  233. data/test/sass/templates/line_numbers.sass +13 -0
  234. data/test/sass/templates/mixin_bork.sass +5 -0
  235. data/test/sass/templates/mixins.sass +76 -0
  236. data/test/sass/templates/multiline.sass +20 -0
  237. data/test/sass/templates/nested.sass +25 -0
  238. data/test/sass/templates/nested_bork1.sass +2 -0
  239. data/test/sass/templates/nested_bork2.sass +2 -0
  240. data/test/sass/templates/nested_bork3.sass +2 -0
  241. data/test/sass/templates/nested_bork4.sass +2 -0
  242. data/test/sass/templates/nested_import.sass +2 -0
  243. data/test/sass/templates/nested_mixin_bork.sass +6 -0
  244. data/test/sass/templates/options.sass +2 -0
  245. data/test/sass/templates/parent_ref.sass +25 -0
  246. data/test/sass/templates/same_name_different_ext.sass +2 -0
  247. data/test/sass/templates/same_name_different_ext.scss +1 -0
  248. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  249. data/test/sass/templates/script.sass +101 -0
  250. data/test/sass/templates/scss_import.scss +12 -0
  251. data/test/sass/templates/scss_importee.scss +1 -0
  252. data/test/sass/templates/single_import_loop.sass +1 -0
  253. data/test/sass/templates/subdir/import_up1.scss +1 -0
  254. data/test/sass/templates/subdir/import_up2.scss +1 -0
  255. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  256. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  257. data/test/sass/templates/subdir/subdir.sass +6 -0
  258. data/test/sass/templates/units.sass +11 -0
  259. data/test/sass/templates/warn.sass +3 -0
  260. data/test/sass/templates/warn_imported.sass +4 -0
  261. data/test/sass/test_helper.rb +8 -0
  262. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  263. data/test/sass/util/normalized_map_test.rb +51 -0
  264. data/test/sass/util/subset_map_test.rb +91 -0
  265. data/test/sass/util_test.rb +467 -0
  266. data/test/sass/value_helpers_test.rb +179 -0
  267. data/test/test_helper.rb +109 -0
  268. metadata +386 -0
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 3.4.0
data/VERSION_NAME ADDED
@@ -0,0 +1 @@
1
+ Selective Steve
data/bin/sass ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # The command line Sass parser.
3
+
4
+ THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
5
+ begin
6
+ require File.dirname(THIS_FILE) + '/../lib/sass'
7
+ rescue LoadError
8
+ require 'sass'
9
+ end
10
+ require 'sass/exec'
11
+
12
+ opts = Sass::Exec::SassScss.new(ARGV, :sass)
13
+ opts.parse!
data/bin/sass-convert ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
4
+ begin
5
+ require File.dirname(THIS_FILE) + '/../lib/sass'
6
+ rescue LoadError
7
+ require 'sass'
8
+ end
9
+ require 'sass/exec'
10
+
11
+ opts = Sass::Exec::SassConvert.new(ARGV)
12
+ opts.parse!
data/bin/scss ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # The command line Sass parser.
3
+
4
+ THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
5
+ begin
6
+ require File.dirname(THIS_FILE) + '/../lib/sass'
7
+ rescue LoadError
8
+ require 'sass'
9
+ end
10
+ require 'sass/exec'
11
+
12
+ opts = Sass::Exec::SassScss.new(ARGV, :scss)
13
+ opts.parse!
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require 'json'
4
+ set :port, 3124
5
+ set :environment, :production
6
+ enable :lock
7
+ Dir.chdir(File.dirname(__FILE__) + "/..")
8
+
9
+ post "/" do
10
+ puts "Recieved payload!"
11
+ puts "Rev: #{`git name-rev HEAD`.strip}"
12
+ system %{rake handle_update --trace REF=#{JSON.parse(params["payload"])["ref"].inspect}}
13
+ end
data/init.rb ADDED
@@ -0,0 +1,18 @@
1
+ begin
2
+ require File.join(File.dirname(__FILE__), 'lib', 'sass') # From here
3
+ rescue LoadError
4
+ begin
5
+ require 'sass' # From gem
6
+ rescue LoadError => e
7
+ # gems:install may be run to install Haml with the skeleton plugin
8
+ # but not the gem itself installed.
9
+ # Don't die if this is the case.
10
+ raise e unless defined?(Rake) &&
11
+ (Rake.application.top_level_tasks.include?('gems') ||
12
+ Rake.application.top_level_tasks.include?('gems:install'))
13
+ end
14
+ end
15
+
16
+ # Load Sass.
17
+ # Sass may be undefined if we're running gems:install.
18
+ require 'sass/plugin' if defined?(Sass)
@@ -0,0 +1,88 @@
1
+ module Sass
2
+ module CacheStores
3
+ # An abstract base class for backends for the Sass cache.
4
+ # Any key-value store can act as such a backend;
5
+ # it just needs to implement the
6
+ # \{#_store} and \{#_retrieve} methods.
7
+ #
8
+ # To use a cache store with Sass,
9
+ # use the {file:SASS_REFERENCE.md#cache_store-option `:cache_store` option}.
10
+ #
11
+ # @abstract
12
+ class Base
13
+ # Store cached contents for later retrieval
14
+ # Must be implemented by all CacheStore subclasses
15
+ #
16
+ # Note: cache contents contain binary data.
17
+ #
18
+ # @param key [String] The key to store the contents under
19
+ # @param version [String] The current sass version.
20
+ # Cached contents must not be retrieved across different versions of sass.
21
+ # @param sha [String] The sha of the sass source.
22
+ # Cached contents must not be retrieved if the sha has changed.
23
+ # @param contents [String] The contents to store.
24
+ def _store(key, version, sha, contents)
25
+ raise "#{self.class} must implement #_store."
26
+ end
27
+
28
+ # Retrieved cached contents.
29
+ # Must be implemented by all subclasses.
30
+ #
31
+ # Note: if the key exists but the sha or version have changed,
32
+ # then the key may be deleted by the cache store, if it wants to do so.
33
+ #
34
+ # @param key [String] The key to retrieve
35
+ # @param version [String] The current sass version.
36
+ # Cached contents must not be retrieved across different versions of sass.
37
+ # @param sha [String] The sha of the sass source.
38
+ # Cached contents must not be retrieved if the sha has changed.
39
+ # @return [String] The contents that were previously stored.
40
+ # @return [NilClass] when the cache key is not found or the version or sha have changed.
41
+ def _retrieve(key, version, sha)
42
+ raise "#{self.class} must implement #_retrieve."
43
+ end
44
+
45
+ # Store a {Sass::Tree::RootNode}.
46
+ #
47
+ # @param key [String] The key to store it under.
48
+ # @param sha [String] The checksum for the contents that are being stored.
49
+ # @param root [Object] The root node to cache.
50
+ def store(key, sha, root)
51
+ _store(key, Sass::VERSION, sha, Marshal.dump(root))
52
+ rescue TypeError, LoadError => e
53
+ Sass::Util.sass_warn "Warning. Error encountered while saving cache #{path_to(key)}: #{e}"
54
+ nil
55
+ end
56
+
57
+ # Retrieve a {Sass::Tree::RootNode}.
58
+ #
59
+ # @param key [String] The key the root element was stored under.
60
+ # @param sha [String] The checksum of the root element's content.
61
+ # @return [Object] The cached object.
62
+ def retrieve(key, sha)
63
+ contents = _retrieve(key, Sass::VERSION, sha)
64
+ Marshal.load(contents) if contents
65
+ rescue EOFError, TypeError, ArgumentError, LoadError => e
66
+ Sass::Util.sass_warn "Warning. Error encountered while reading cache #{path_to(key)}: #{e}"
67
+ nil
68
+ end
69
+
70
+ # Return the key for the sass file.
71
+ #
72
+ # The `(sass_dirname, sass_basename)` pair
73
+ # should uniquely identify the Sass document,
74
+ # but otherwise there are no restrictions on their content.
75
+ #
76
+ # @param sass_dirname [String]
77
+ # The fully-expanded location of the Sass file.
78
+ # This corresponds to the directory name on a filesystem.
79
+ # @param sass_basename [String] The name of the Sass file that is being referenced.
80
+ # This corresponds to the basename on a filesystem.
81
+ def key(sass_dirname, sass_basename)
82
+ dir = Digest::SHA1.hexdigest(sass_dirname)
83
+ filename = "#{sass_basename}c"
84
+ "#{dir}/#{filename}"
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,34 @@
1
+ module Sass
2
+ module CacheStores
3
+ # A meta-cache that chains multiple caches together.
4
+ # Specifically:
5
+ #
6
+ # * All `#store`s are passed to all caches.
7
+ # * `#retrieve`s are passed to each cache until one has a hit.
8
+ # * When one cache has a hit, the value is `#store`d in all earlier caches.
9
+ class Chain < Base
10
+ # Create a new cache chaining the given caches.
11
+ #
12
+ # @param caches [Array<Sass::CacheStores::Base>] The caches to chain.
13
+ def initialize(*caches)
14
+ @caches = caches
15
+ end
16
+
17
+ # @see Base#store
18
+ def store(key, sha, obj)
19
+ @caches.each {|c| c.store(key, sha, obj)}
20
+ end
21
+
22
+ # @see Base#retrieve
23
+ def retrieve(key, sha)
24
+ @caches.each_with_index do |c, i|
25
+ obj = c.retrieve(key, sha)
26
+ next unless obj
27
+ @caches[0...i].each {|prev| prev.store(key, sha, obj)}
28
+ return obj
29
+ end
30
+ nil
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,60 @@
1
+ require 'fileutils'
2
+
3
+ module Sass
4
+ module CacheStores
5
+ # A backend for the Sass cache using the filesystem.
6
+ class Filesystem < Base
7
+ # The directory where the cached files will be stored.
8
+ #
9
+ # @return [String]
10
+ attr_accessor :cache_location
11
+
12
+ # @param cache_location [String] see \{#cache\_location}
13
+ def initialize(cache_location)
14
+ @cache_location = cache_location
15
+ end
16
+
17
+ # @see Base#\_retrieve
18
+ def _retrieve(key, version, sha)
19
+ return unless File.readable?(path_to(key))
20
+ File.open(path_to(key), "rb") do |f|
21
+ if f.readline("\n").strip == version && f.readline("\n").strip == sha
22
+ return f.read
23
+ end
24
+ end
25
+ begin
26
+ File.unlink path_to(key)
27
+ rescue Errno::ENOENT
28
+ # Already deleted. Race condition?
29
+ end
30
+ nil
31
+ rescue EOFError, TypeError, ArgumentError => e
32
+ Sass::Util.sass_warn "Warning. Error encountered while reading cache #{path_to(key)}: #{e}"
33
+ end
34
+
35
+ # @see Base#\_store
36
+ def _store(key, version, sha, contents)
37
+ compiled_filename = path_to(key)
38
+ FileUtils.mkdir_p(File.dirname(compiled_filename))
39
+ Sass::Util.atomic_create_and_write_file(compiled_filename, 0600) do |f|
40
+ f.puts(version)
41
+ f.puts(sha)
42
+ f.write(contents)
43
+ end
44
+ rescue Errno::EACCES
45
+ # pass
46
+ end
47
+
48
+ private
49
+
50
+ # Returns the path to a file for the given key.
51
+ #
52
+ # @param key [String]
53
+ # @return [String] The path to the cache file.
54
+ def path_to(key)
55
+ key = key.gsub(/[<>:\\|?*%]/) {|c| "%%%03d" % Sass::Util.ord(c)}
56
+ File.join(cache_location, key)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,47 @@
1
+ module Sass
2
+ module CacheStores
3
+ # A backend for the Sass cache using in-process memory.
4
+ class Memory < Base
5
+ # Since the {Memory} store is stored in the Sass tree's options hash,
6
+ # when the options get serialized as part of serializing the tree,
7
+ # you get crazy exponential growth in the size of the cached objects
8
+ # unless you don't dump the cache.
9
+ #
10
+ # @private
11
+ def _dump(depth)
12
+ ""
13
+ end
14
+
15
+ # If we deserialize this class, just make a new empty one.
16
+ #
17
+ # @private
18
+ def self._load(repr)
19
+ Memory.new
20
+ end
21
+
22
+ # Create a new, empty cache store.
23
+ def initialize
24
+ @contents = {}
25
+ end
26
+
27
+ # @see Base#retrieve
28
+ def retrieve(key, sha)
29
+ if @contents.has_key?(key)
30
+ return unless @contents[key][:sha] == sha
31
+ obj = @contents[key][:obj]
32
+ obj.respond_to?(:deep_copy) ? obj.deep_copy : obj.dup
33
+ end
34
+ end
35
+
36
+ # @see Base#store
37
+ def store(key, sha, obj)
38
+ @contents[key] = {:sha => sha, :obj => obj}
39
+ end
40
+
41
+ # Destructively clear the cache.
42
+ def reset!
43
+ @contents = {}
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,25 @@
1
+ module Sass
2
+ module CacheStores
3
+ # Doesn't store anything, but records what things it should have stored.
4
+ # This doesn't currently have any use except for testing and debugging.
5
+ #
6
+ # @private
7
+ class Null < Base
8
+ def initialize
9
+ @keys = {}
10
+ end
11
+
12
+ def _retrieve(key, version, sha)
13
+ nil
14
+ end
15
+
16
+ def _store(key, version, sha, contents)
17
+ @keys[key] = true
18
+ end
19
+
20
+ def was_set?(key)
21
+ @keys[key]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ require 'stringio'
2
+
3
+ module Sass
4
+ # Sass cache stores are in charge of storing cached information,
5
+ # especially parse trees for Sass documents.
6
+ #
7
+ # User-created importers must inherit from {CacheStores::Base}.
8
+ module CacheStores
9
+ end
10
+ end
11
+
12
+ require 'sass/cache_stores/base'
13
+ require 'sass/cache_stores/filesystem'
14
+ require 'sass/cache_stores/memory'
15
+ require 'sass/cache_stores/chain'
@@ -0,0 +1,67 @@
1
+ module Sass
2
+ # A lightweight infrastructure for defining and running callbacks.
3
+ # Callbacks are defined using \{#define\_callback\} at the class level,
4
+ # and called using `run_#{name}` at the instance level.
5
+ #
6
+ # Clients can add callbacks by calling the generated `on_#{name}` method,
7
+ # and passing in a block that's run when the callback is activated.
8
+ #
9
+ # @example Define a callback
10
+ # class Munger
11
+ # extend Sass::Callbacks
12
+ # define_callback :string_munged
13
+ #
14
+ # def munge(str)
15
+ # res = str.gsub(/[a-z]/, '\1\1')
16
+ # run_string_munged str, res
17
+ # res
18
+ # end
19
+ # end
20
+ #
21
+ # @example Use a callback
22
+ # m = Munger.new
23
+ # m.on_string_munged {|str, res| puts "#{str} was munged into #{res}!"}
24
+ # m.munge "bar" #=> bar was munged into bbaarr!
25
+ module Callbacks
26
+ # Automatically includes {InstanceMethods}
27
+ # when something extends this module.
28
+ #
29
+ # @param base [Module]
30
+ def self.extended(base)
31
+ base.send(:include, InstanceMethods)
32
+ end
33
+
34
+ protected
35
+
36
+ module InstanceMethods
37
+ # Removes all callbacks registered against this object.
38
+ def clear_callbacks!
39
+ @_sass_callbacks = {}
40
+ end
41
+ end
42
+
43
+ # Define a callback with the given name.
44
+ # This will define an `on_#{name}` method
45
+ # that registers a block,
46
+ # and a `run_#{name}` method that runs that block
47
+ # (optionall with some arguments).
48
+ #
49
+ # @param name [Symbol] The name of the callback
50
+ # @return [void]
51
+ def define_callback(name)
52
+ class_eval <<RUBY, __FILE__, __LINE__ + 1
53
+ def on_#{name}(&block)
54
+ @_sass_callbacks ||= {}
55
+ (@_sass_callbacks[#{name.inspect}] ||= []) << block
56
+ end
57
+
58
+ def run_#{name}(*args)
59
+ return unless @_sass_callbacks
60
+ return unless @_sass_callbacks[#{name.inspect}]
61
+ @_sass_callbacks[#{name.inspect}].each {|c| c[*args]}
62
+ end
63
+ private :run_#{name}
64
+ RUBY
65
+ end
66
+ end
67
+ end
data/lib/sass/css.rb ADDED
@@ -0,0 +1,407 @@
1
+ require File.dirname(__FILE__) + '/../sass'
2
+ require 'sass/tree/node'
3
+ require 'sass/scss/css_parser'
4
+
5
+ module Sass
6
+ # This class converts CSS documents into Sass or SCSS templates.
7
+ # It works by parsing the CSS document into a {Sass::Tree} structure,
8
+ # and then applying various transformations to the structure
9
+ # to produce more concise and idiomatic Sass/SCSS.
10
+ #
11
+ # Example usage:
12
+ #
13
+ # Sass::CSS.new("p { color: blue }").render(:sass) #=> "p\n color: blue"
14
+ # Sass::CSS.new("p { color: blue }").render(:scss) #=> "p {\n color: blue; }"
15
+ class CSS
16
+ # @param template [String] The CSS stylesheet.
17
+ # This stylesheet can be encoded using any encoding
18
+ # that can be converted to Unicode.
19
+ # If the stylesheet contains an `@charset` declaration,
20
+ # that overrides the Ruby encoding
21
+ # (see {file:SASS_REFERENCE.md#encodings the encoding documentation})
22
+ # @option options :old [Boolean] (false)
23
+ # Whether or not to output old property syntax
24
+ # (`:color blue` as opposed to `color: blue`).
25
+ # This is only meaningful when generating Sass code,
26
+ # rather than SCSS.
27
+ # @option options :indent [String] (" ")
28
+ # The string to use for indenting each line. Defaults to two spaces.
29
+ def initialize(template, options = {})
30
+ if template.is_a? IO
31
+ template = template.read
32
+ end
33
+
34
+ @options = options.dup
35
+ # Backwards compatibility
36
+ @options[:old] = true if @options[:alternate] == false
37
+ @template = template
38
+ end
39
+
40
+ # Converts the CSS template into Sass or SCSS code.
41
+ #
42
+ # @param fmt [Symbol] `:sass` or `:scss`, designating the format to return.
43
+ # @return [String] The resulting Sass or SCSS code
44
+ # @raise [Sass::SyntaxError] if there's an error parsing the CSS template
45
+ def render(fmt = :sass)
46
+ check_encoding!
47
+ build_tree.send("to_#{fmt}", @options).strip + "\n"
48
+ rescue Sass::SyntaxError => err
49
+ err.modify_backtrace(:filename => @options[:filename] || '(css)')
50
+ raise err
51
+ end
52
+
53
+ # Returns the original encoding of the document,
54
+ # or `nil` under Ruby 1.8.
55
+ #
56
+ # @return [Encoding, nil]
57
+ # @raise [Encoding::UndefinedConversionError] if the source encoding
58
+ # cannot be converted to UTF-8
59
+ # @raise [ArgumentError] if the document uses an unknown encoding with `@charset`
60
+ def source_encoding
61
+ check_encoding!
62
+ @original_encoding
63
+ end
64
+
65
+ private
66
+
67
+ def check_encoding!
68
+ return if @checked_encoding
69
+ @checked_encoding = true
70
+ @template, @original_encoding = Sass::Util.check_sass_encoding(@template)
71
+ end
72
+
73
+ # Parses the CSS template and applies various transformations
74
+ #
75
+ # @return [Tree::Node] The root node of the parsed tree
76
+ def build_tree
77
+ root = Sass::SCSS::CssParser.new(@template, @options[:filename], nil).parse
78
+ parse_selectors root
79
+ expand_commas root
80
+ nest_seqs root
81
+ parent_ref_rules root
82
+ flatten_rules root
83
+ bubble_subject root
84
+ fold_commas root
85
+ dump_selectors root
86
+ root
87
+ end
88
+
89
+ # Parse all the selectors in the document and assign them to
90
+ # {Sass::Tree::RuleNode#parsed_rules}.
91
+ #
92
+ # @param root [Tree::Node] The parent node
93
+ def parse_selectors(root)
94
+ root.children.each do |child|
95
+ next parse_selectors(child) if child.is_a?(Tree::DirectiveNode)
96
+ next unless child.is_a?(Tree::RuleNode)
97
+ parser = Sass::SCSS::CssParser.new(child.rule.first, child.filename, nil, child.line)
98
+ child.parsed_rules = parser.parse_selector
99
+ end
100
+ end
101
+
102
+ # Transform
103
+ #
104
+ # foo, bar, baz
105
+ # color: blue
106
+ #
107
+ # into
108
+ #
109
+ # foo
110
+ # color: blue
111
+ # bar
112
+ # color: blue
113
+ # baz
114
+ # color: blue
115
+ #
116
+ # @param root [Tree::Node] The parent node
117
+ def expand_commas(root)
118
+ root.children.map! do |child|
119
+ # child.parsed_rules.members.size > 1 iff the rule contains a comma
120
+ unless child.is_a?(Tree::RuleNode) && child.parsed_rules.members.size > 1
121
+ expand_commas(child) if child.is_a?(Tree::DirectiveNode)
122
+ next child
123
+ end
124
+ child.parsed_rules.members.map do |seq|
125
+ node = Tree::RuleNode.new([])
126
+ node.parsed_rules = make_cseq(seq)
127
+ node.children = child.children
128
+ node
129
+ end
130
+ end
131
+ root.children.flatten!
132
+ end
133
+
134
+ # Make rules use nesting so that
135
+ #
136
+ # foo
137
+ # color: green
138
+ # foo bar
139
+ # color: red
140
+ # foo baz
141
+ # color: blue
142
+ #
143
+ # becomes
144
+ #
145
+ # foo
146
+ # color: green
147
+ # bar
148
+ # color: red
149
+ # baz
150
+ # color: blue
151
+ #
152
+ # @param root [Tree::Node] The parent node
153
+ def nest_seqs(root)
154
+ current_rule = nil
155
+ root.children.map! do |child|
156
+ unless child.is_a?(Tree::RuleNode)
157
+ nest_seqs(child) if child.is_a?(Tree::DirectiveNode)
158
+ next child
159
+ end
160
+
161
+ seq = first_seq(child)
162
+ seq.members.reject! {|sseq| sseq == "\n"}
163
+ first, rest = seq.members.first, seq.members[1..-1]
164
+
165
+ if current_rule.nil? || first_sseq(current_rule) != first
166
+ current_rule = Tree::RuleNode.new([])
167
+ current_rule.parsed_rules = make_seq(first)
168
+ end
169
+
170
+ if rest.empty?
171
+ current_rule.children += child.children
172
+ else
173
+ child.parsed_rules = make_seq(*rest)
174
+ current_rule << child
175
+ end
176
+
177
+ current_rule
178
+ end
179
+ root.children.compact!
180
+ root.children.uniq!
181
+
182
+ root.children.each {|v| nest_seqs(v)}
183
+ end
184
+
185
+ # Make rules use parent refs so that
186
+ #
187
+ # foo
188
+ # color: green
189
+ # foo.bar
190
+ # color: blue
191
+ #
192
+ # becomes
193
+ #
194
+ # foo
195
+ # color: green
196
+ # &.bar
197
+ # color: blue
198
+ #
199
+ # @param root [Tree::Node] The parent node
200
+ def parent_ref_rules(root)
201
+ current_rule = nil
202
+ root.children.map! do |child|
203
+ unless child.is_a?(Tree::RuleNode)
204
+ parent_ref_rules(child) if child.is_a?(Tree::DirectiveNode)
205
+ next child
206
+ end
207
+
208
+ sseq = first_sseq(child)
209
+ next child unless sseq.is_a?(Sass::Selector::SimpleSequence)
210
+
211
+ firsts, rest = [sseq.members.first], sseq.members[1..-1]
212
+ firsts.push rest.shift if firsts.first.is_a?(Sass::Selector::Parent)
213
+
214
+ last_simple_subject = rest.empty? && sseq.subject?
215
+ if current_rule.nil? || first_sseq(current_rule).members != firsts ||
216
+ !!first_sseq(current_rule).subject? != !!last_simple_subject
217
+ current_rule = Tree::RuleNode.new([])
218
+ current_rule.parsed_rules = make_sseq(last_simple_subject, *firsts)
219
+ end
220
+
221
+ if rest.empty?
222
+ current_rule.children += child.children
223
+ else
224
+ rest.unshift Sass::Selector::Parent.new
225
+ child.parsed_rules = make_sseq(sseq.subject?, *rest)
226
+ current_rule << child
227
+ end
228
+
229
+ current_rule
230
+ end
231
+ root.children.compact!
232
+ root.children.uniq!
233
+
234
+ root.children.each {|v| parent_ref_rules(v)}
235
+ end
236
+
237
+ # Flatten rules so that
238
+ #
239
+ # foo
240
+ # bar
241
+ # color: red
242
+ #
243
+ # becomes
244
+ #
245
+ # foo bar
246
+ # color: red
247
+ #
248
+ # and
249
+ #
250
+ # foo
251
+ # &.bar
252
+ # color: blue
253
+ #
254
+ # becomes
255
+ #
256
+ # foo.bar
257
+ # color: blue
258
+ #
259
+ # @param root [Tree::Node] The parent node
260
+ def flatten_rules(root)
261
+ root.children.each do |child|
262
+ case child
263
+ when Tree::RuleNode
264
+ flatten_rule(child)
265
+ when Tree::DirectiveNode
266
+ flatten_rules(child)
267
+ end
268
+ end
269
+ end
270
+
271
+ # Flattens a single rule.
272
+ #
273
+ # @param rule [Tree::RuleNode] The candidate for flattening
274
+ # @see #flatten_rules
275
+ def flatten_rule(rule)
276
+ while rule.children.size == 1 && rule.children.first.is_a?(Tree::RuleNode)
277
+ child = rule.children.first
278
+
279
+ if first_simple_sel(child).is_a?(Sass::Selector::Parent)
280
+ rule.parsed_rules = child.parsed_rules.resolve_parent_refs(rule.parsed_rules)
281
+ else
282
+ rule.parsed_rules = make_seq(*(first_seq(rule).members + first_seq(child).members))
283
+ end
284
+
285
+ rule.children = child.children
286
+ end
287
+
288
+ flatten_rules(rule)
289
+ end
290
+
291
+ def bubble_subject(root)
292
+ root.children.each do |child|
293
+ bubble_subject(child) if child.is_a?(Tree::RuleNode) || child.is_a?(Tree::DirectiveNode)
294
+ next unless child.is_a?(Tree::RuleNode) && !child.children.empty?
295
+ next unless child.children.all? do |c|
296
+ next unless c.is_a?(Tree::RuleNode)
297
+ first_simple_sel(c).is_a?(Sass::Selector::Parent) && first_sseq(c).subject?
298
+ end
299
+ first_sseq(child).subject = true
300
+ child.children.each {|c| first_sseq(c).subject = false}
301
+ end
302
+ end
303
+
304
+ # Transform
305
+ #
306
+ # foo
307
+ # bar
308
+ # color: blue
309
+ # baz
310
+ # color: blue
311
+ #
312
+ # into
313
+ #
314
+ # foo
315
+ # bar, baz
316
+ # color: blue
317
+ #
318
+ # @param root [Tree::Node] The parent node
319
+ def fold_commas(root)
320
+ prev_rule = nil
321
+ root.children.map! do |child|
322
+ unless child.is_a?(Tree::RuleNode)
323
+ fold_commas(child) if child.is_a?(Tree::DirectiveNode)
324
+ next child
325
+ end
326
+
327
+ if prev_rule && prev_rule.children.map {|c| c.to_sass} == child.children.map {|c| c.to_sass}
328
+ prev_rule.parsed_rules.members << first_seq(child)
329
+ next nil
330
+ end
331
+
332
+ fold_commas(child)
333
+ prev_rule = child
334
+ child
335
+ end
336
+ root.children.compact!
337
+ end
338
+
339
+ # Dump all the parsed {Sass::Tree::RuleNode} selectors to strings.
340
+ #
341
+ # @param root [Tree::Node] The parent node
342
+ def dump_selectors(root)
343
+ root.children.each do |child|
344
+ next dump_selectors(child) if child.is_a?(Tree::DirectiveNode)
345
+ next unless child.is_a?(Tree::RuleNode)
346
+ child.rule = [child.parsed_rules.to_s]
347
+ dump_selectors(child)
348
+ end
349
+ end
350
+
351
+ # Create a {Sass::Selector::CommaSequence}.
352
+ #
353
+ # @param seqs [Array<Sass::Selector::Sequence>]
354
+ # @return [Sass::Selector::CommaSequence]
355
+ def make_cseq(*seqs)
356
+ Sass::Selector::CommaSequence.new(seqs)
357
+ end
358
+
359
+ # Create a {Sass::Selector::CommaSequence} containing only a single
360
+ # {Sass::Selector::Sequence}.
361
+ #
362
+ # @param sseqs [Array<Sass::Selector::Sequence, String>]
363
+ # @return [Sass::Selector::CommaSequence]
364
+ def make_seq(*sseqs)
365
+ make_cseq(Sass::Selector::Sequence.new(sseqs))
366
+ end
367
+
368
+ # Create a {Sass::Selector::CommaSequence} containing only a single
369
+ # {Sass::Selector::Sequence} which in turn contains only a single
370
+ # {Sass::Selector::SimpleSequence}.
371
+ #
372
+ # @param subject [Boolean] Whether this is a subject selector
373
+ # @param sseqs [Array<Sass::Selector::Sequence, String>]
374
+ # @return [Sass::Selector::CommaSequence]
375
+ def make_sseq(subject, *sseqs)
376
+ make_seq(Sass::Selector::SimpleSequence.new(sseqs, subject))
377
+ end
378
+
379
+ # Return the first {Sass::Selector::Sequence} in a {Sass::Tree::RuleNode}.
380
+ #
381
+ # @param rule [Sass::Tree::RuleNode]
382
+ # @return [Sass::Selector::Sequence]
383
+ def first_seq(rule)
384
+ rule.parsed_rules.members.first
385
+ end
386
+
387
+ # Return the first {Sass::Selector::SimpleSequence} in a
388
+ # {Sass::Tree::RuleNode}.
389
+ #
390
+ # @param rule [Sass::Tree::RuleNode]
391
+ # @return [Sass::Selector::SimpleSequence, String]
392
+ def first_sseq(rule)
393
+ first_seq(rule).members.first
394
+ end
395
+
396
+ # Return the first {Sass::Selector::Simple} in a {Sass::Tree::RuleNode},
397
+ # unless the rule begins with a combinator.
398
+ #
399
+ # @param rule [Sass::Tree::RuleNode]
400
+ # @return [Sass::Selector::Simple?]
401
+ def first_simple_sel(rule)
402
+ sseq = first_sseq(rule)
403
+ return unless sseq.is_a?(Sass::Selector::SimpleSequence)
404
+ sseq.members.first
405
+ end
406
+ end
407
+ end