oreorenasass 3.4.4 → 3.4.5

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 (176) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +50 -70
  4. data/Rakefile +5 -26
  5. data/VERSION +1 -1
  6. data/VERSION_NAME +1 -1
  7. data/bin/sass +1 -1
  8. data/bin/scss +1 -1
  9. data/lib/sass.rb +12 -19
  10. data/lib/sass/cache_stores/base.rb +2 -2
  11. data/lib/sass/cache_stores/chain.rb +1 -2
  12. data/lib/sass/cache_stores/filesystem.rb +5 -1
  13. data/lib/sass/cache_stores/memory.rb +1 -1
  14. data/lib/sass/cache_stores/null.rb +2 -2
  15. data/lib/sass/callbacks.rb +0 -1
  16. data/lib/sass/css.rb +13 -11
  17. data/lib/sass/engine.rb +173 -424
  18. data/lib/sass/environment.rb +58 -148
  19. data/lib/sass/error.rb +14 -11
  20. data/lib/sass/exec.rb +703 -5
  21. data/lib/sass/importers/base.rb +6 -49
  22. data/lib/sass/importers/filesystem.rb +19 -44
  23. data/lib/sass/logger.rb +4 -1
  24. data/lib/sass/logger/base.rb +4 -2
  25. data/lib/sass/logger/log_level.rb +7 -3
  26. data/lib/sass/media.rb +23 -20
  27. data/lib/sass/plugin.rb +7 -7
  28. data/lib/sass/plugin/compiler.rb +145 -304
  29. data/lib/sass/plugin/configuration.rb +23 -18
  30. data/lib/sass/plugin/merb.rb +1 -1
  31. data/lib/sass/plugin/staleness_checker.rb +3 -3
  32. data/lib/sass/repl.rb +3 -3
  33. data/lib/sass/script.rb +8 -35
  34. data/lib/sass/script/{value/arg_list.rb → arg_list.rb} +25 -9
  35. data/lib/sass/script/bool.rb +18 -0
  36. data/lib/sass/script/color.rb +606 -0
  37. data/lib/sass/script/css_lexer.rb +4 -8
  38. data/lib/sass/script/css_parser.rb +2 -5
  39. data/lib/sass/script/funcall.rb +245 -0
  40. data/lib/sass/script/functions.rb +408 -1491
  41. data/lib/sass/script/interpolation.rb +79 -0
  42. data/lib/sass/script/lexer.rb +68 -172
  43. data/lib/sass/script/list.rb +85 -0
  44. data/lib/sass/script/literal.rb +221 -0
  45. data/lib/sass/script/{tree/node.rb → node.rb} +12 -22
  46. data/lib/sass/script/{value/null.rb → null.rb} +7 -14
  47. data/lib/sass/script/{value/number.rb → number.rb} +75 -152
  48. data/lib/sass/script/{tree/operation.rb → operation.rb} +24 -17
  49. data/lib/sass/script/parser.rb +110 -245
  50. data/lib/sass/script/string.rb +51 -0
  51. data/lib/sass/script/{tree/string_interpolation.rb → string_interpolation.rb} +4 -5
  52. data/lib/sass/script/{tree/unary_operation.rb → unary_operation.rb} +6 -6
  53. data/lib/sass/script/variable.rb +58 -0
  54. data/lib/sass/scss/css_parser.rb +3 -9
  55. data/lib/sass/scss/parser.rb +421 -450
  56. data/lib/sass/scss/rx.rb +11 -19
  57. data/lib/sass/scss/static_parser.rb +7 -321
  58. data/lib/sass/selector.rb +194 -68
  59. data/lib/sass/selector/abstract_sequence.rb +14 -29
  60. data/lib/sass/selector/comma_sequence.rb +25 -108
  61. data/lib/sass/selector/sequence.rb +66 -159
  62. data/lib/sass/selector/simple.rb +25 -23
  63. data/lib/sass/selector/simple_sequence.rb +63 -173
  64. data/lib/sass/shared.rb +1 -1
  65. data/lib/sass/supports.rb +15 -13
  66. data/lib/sass/tree/charset_node.rb +1 -1
  67. data/lib/sass/tree/comment_node.rb +3 -3
  68. data/lib/sass/tree/css_import_node.rb +11 -11
  69. data/lib/sass/tree/debug_node.rb +2 -2
  70. data/lib/sass/tree/directive_node.rb +4 -21
  71. data/lib/sass/tree/each_node.rb +8 -8
  72. data/lib/sass/tree/extend_node.rb +7 -14
  73. data/lib/sass/tree/for_node.rb +4 -4
  74. data/lib/sass/tree/function_node.rb +4 -9
  75. data/lib/sass/tree/if_node.rb +1 -1
  76. data/lib/sass/tree/import_node.rb +5 -4
  77. data/lib/sass/tree/media_node.rb +14 -4
  78. data/lib/sass/tree/mixin_def_node.rb +4 -4
  79. data/lib/sass/tree/mixin_node.rb +8 -21
  80. data/lib/sass/tree/node.rb +12 -54
  81. data/lib/sass/tree/prop_node.rb +20 -39
  82. data/lib/sass/tree/return_node.rb +2 -3
  83. data/lib/sass/tree/root_node.rb +3 -19
  84. data/lib/sass/tree/rule_node.rb +22 -35
  85. data/lib/sass/tree/supports_node.rb +13 -0
  86. data/lib/sass/tree/trace_node.rb +1 -2
  87. data/lib/sass/tree/variable_node.rb +3 -9
  88. data/lib/sass/tree/visitors/base.rb +8 -5
  89. data/lib/sass/tree/visitors/check_nesting.rb +19 -49
  90. data/lib/sass/tree/visitors/convert.rb +56 -74
  91. data/lib/sass/tree/visitors/cssize.rb +74 -202
  92. data/lib/sass/tree/visitors/deep_copy.rb +5 -10
  93. data/lib/sass/tree/visitors/extend.rb +7 -7
  94. data/lib/sass/tree/visitors/perform.rb +185 -278
  95. data/lib/sass/tree/visitors/set_options.rb +6 -20
  96. data/lib/sass/tree/visitors/to_css.rb +81 -234
  97. data/lib/sass/tree/warn_node.rb +2 -2
  98. data/lib/sass/tree/while_node.rb +2 -2
  99. data/lib/sass/util.rb +152 -522
  100. data/lib/sass/util/multibyte_string_scanner.rb +0 -2
  101. data/lib/sass/util/subset_map.rb +3 -4
  102. data/lib/sass/util/test.rb +1 -0
  103. data/lib/sass/version.rb +22 -20
  104. data/test/Gemfile +3 -0
  105. data/test/Gemfile.lock +10 -0
  106. data/test/sass/cache_test.rb +20 -62
  107. data/test/sass/callbacks_test.rb +1 -1
  108. data/test/sass/conversion_test.rb +2 -296
  109. data/test/sass/css2sass_test.rb +4 -23
  110. data/test/sass/engine_test.rb +354 -411
  111. data/test/sass/exec_test.rb +2 -2
  112. data/test/sass/extend_test.rb +145 -324
  113. data/test/sass/functions_test.rb +86 -873
  114. data/test/sass/importer_test.rb +21 -241
  115. data/test/sass/logger_test.rb +1 -1
  116. data/test/sass/more_results/more_import.css +1 -1
  117. data/test/sass/plugin_test.rb +26 -16
  118. data/test/sass/results/compact.css +1 -1
  119. data/test/sass/results/complex.css +4 -4
  120. data/test/sass/results/expanded.css +1 -1
  121. data/test/sass/results/import.css +1 -1
  122. data/test/sass/results/import_charset_ibm866.css +2 -2
  123. data/test/sass/results/mixins.css +17 -17
  124. data/test/sass/results/nested.css +1 -1
  125. data/test/sass/results/parent_ref.css +2 -2
  126. data/test/sass/results/script.css +3 -3
  127. data/test/sass/results/scss_import.css +1 -1
  128. data/test/sass/script_conversion_test.rb +7 -36
  129. data/test/sass/script_test.rb +53 -485
  130. data/test/sass/scss/css_test.rb +28 -143
  131. data/test/sass/scss/rx_test.rb +4 -4
  132. data/test/sass/scss/scss_test.rb +325 -2119
  133. data/test/sass/templates/scss_import.scss +1 -2
  134. data/test/sass/test_helper.rb +1 -1
  135. data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
  136. data/test/sass/util/subset_map_test.rb +2 -2
  137. data/test/sass/util_test.rb +1 -86
  138. data/test/test_helper.rb +8 -37
  139. metadata +19 -66
  140. data/lib/sass/exec/base.rb +0 -187
  141. data/lib/sass/exec/sass_convert.rb +0 -264
  142. data/lib/sass/exec/sass_scss.rb +0 -424
  143. data/lib/sass/features.rb +0 -47
  144. data/lib/sass/script/tree.rb +0 -16
  145. data/lib/sass/script/tree/funcall.rb +0 -306
  146. data/lib/sass/script/tree/interpolation.rb +0 -118
  147. data/lib/sass/script/tree/list_literal.rb +0 -77
  148. data/lib/sass/script/tree/literal.rb +0 -45
  149. data/lib/sass/script/tree/map_literal.rb +0 -64
  150. data/lib/sass/script/tree/selector.rb +0 -26
  151. data/lib/sass/script/tree/variable.rb +0 -57
  152. data/lib/sass/script/value.rb +0 -11
  153. data/lib/sass/script/value/base.rb +0 -240
  154. data/lib/sass/script/value/bool.rb +0 -35
  155. data/lib/sass/script/value/color.rb +0 -680
  156. data/lib/sass/script/value/helpers.rb +0 -262
  157. data/lib/sass/script/value/list.rb +0 -113
  158. data/lib/sass/script/value/map.rb +0 -70
  159. data/lib/sass/script/value/string.rb +0 -97
  160. data/lib/sass/selector/pseudo.rb +0 -256
  161. data/lib/sass/source/map.rb +0 -210
  162. data/lib/sass/source/position.rb +0 -39
  163. data/lib/sass/source/range.rb +0 -41
  164. data/lib/sass/stack.rb +0 -120
  165. data/lib/sass/tree/at_root_node.rb +0 -83
  166. data/lib/sass/tree/error_node.rb +0 -18
  167. data/lib/sass/tree/keyframe_rule_node.rb +0 -15
  168. data/lib/sass/util/cross_platform_random.rb +0 -19
  169. data/lib/sass/util/normalized_map.rb +0 -130
  170. data/lib/sass/util/ordered_hash.rb +0 -192
  171. data/test/sass/compiler_test.rb +0 -232
  172. data/test/sass/encoding_test.rb +0 -219
  173. data/test/sass/source_map_test.rb +0 -977
  174. data/test/sass/superselector_test.rb +0 -191
  175. data/test/sass/util/normalized_map_test.rb +0 -51
  176. data/test/sass/value_helpers_test.rb +0 -179
@@ -1,264 +0,0 @@
1
- require 'optparse'
2
- require 'fileutils'
3
-
4
- module Sass::Exec
5
- # The `sass-convert` executable.
6
- class SassConvert < Base
7
- # @param args [Array<String>] The command-line arguments
8
- def initialize(args)
9
- super
10
- require 'sass'
11
- @options[:for_tree] = {}
12
- @options[:for_engine] = {:cache => false, :read_cache => true}
13
- end
14
-
15
- # Tells optparse how to parse the arguments.
16
- #
17
- # @param opts [OptionParser]
18
- def set_opts(opts)
19
- opts.banner = <<END
20
- Usage: sass-convert [options] [INPUT] [OUTPUT]
21
-
22
- Description:
23
- Converts between CSS, indented syntax, and SCSS files. For example,
24
- this can convert from the indented syntax to SCSS, or from CSS to
25
- SCSS (adding appropriate nesting).
26
- END
27
-
28
- common_options(opts)
29
- style(opts)
30
- input_and_output(opts)
31
- miscellaneous(opts)
32
- end
33
-
34
- # Processes the options set by the command-line arguments,
35
- # and runs the CSS compiler appropriately.
36
- def process_result
37
- require 'sass'
38
-
39
- if @options[:recursive]
40
- process_directory
41
- return
42
- end
43
-
44
- super
45
- input = @options[:input]
46
- if File.directory?(input)
47
- raise "Error: '#{input.path}' is a directory (did you mean to use --recursive?)"
48
- end
49
- output = @options[:output]
50
- output = input if @options[:in_place]
51
- process_file(input, output)
52
- end
53
-
54
- private
55
-
56
- def common_options(opts)
57
- opts.separator ''
58
- opts.separator 'Common Options:'
59
-
60
- opts.on('-F', '--from FORMAT',
61
- 'The format to convert from. Can be css, scss, sass.',
62
- 'By default, this is inferred from the input filename.',
63
- 'If there is none, defaults to css.') do |name|
64
- @options[:from] = name.downcase.to_sym
65
- raise "sass-convert no longer supports LessCSS." if @options[:from] == :less
66
- unless [:css, :scss, :sass].include?(@options[:from])
67
- raise "Unknown format for sass-convert --from: #{name}"
68
- end
69
- end
70
-
71
- opts.on('-T', '--to FORMAT',
72
- 'The format to convert to. Can be scss or sass.',
73
- 'By default, this is inferred from the output filename.',
74
- 'If there is none, defaults to sass.') do |name|
75
- @options[:to] = name.downcase.to_sym
76
- unless [:scss, :sass].include?(@options[:to])
77
- raise "Unknown format for sass-convert --to: #{name}"
78
- end
79
- end
80
-
81
- opts.on('-i', '--in-place',
82
- 'Convert a file to its own syntax.',
83
- 'This can be used to update some deprecated syntax.') do
84
- @options[:in_place] = true
85
- end
86
-
87
- opts.on('-R', '--recursive',
88
- 'Convert all the files in a directory. Requires --from and --to.') do
89
- @options[:recursive] = true
90
- end
91
-
92
- opts.on("-?", "-h", "--help", "Show this help message.") do
93
- puts opts
94
- exit
95
- end
96
-
97
- opts.on("-v", "--version", "Print the Sass version.") do
98
- puts("Sass #{Sass.version[:string]}")
99
- exit
100
- end
101
- end
102
-
103
- def style(opts)
104
- opts.separator ''
105
- opts.separator 'Style:'
106
-
107
- opts.on('--dasherize', 'Convert underscores to dashes.') do
108
- @options[:for_tree][:dasherize] = true
109
- end
110
-
111
- opts.on('--indent NUM',
112
- 'How many spaces to use for each level of indentation. Defaults to 2.',
113
- '"t" means use hard tabs.') do |indent|
114
-
115
- if indent == 't'
116
- @options[:for_tree][:indent] = "\t"
117
- else
118
- @options[:for_tree][:indent] = " " * indent.to_i
119
- end
120
- end
121
-
122
- opts.on('--old', 'Output the old-style ":prop val" property syntax.',
123
- 'Only meaningful when generating Sass.') do
124
- @options[:for_tree][:old] = true
125
- end
126
- end
127
-
128
- def input_and_output(opts)
129
- opts.separator ''
130
- opts.separator 'Input and Output:'
131
-
132
- opts.on('-s', '--stdin', :NONE,
133
- 'Read input from standard input instead of an input file.',
134
- 'This is the default if no input file is specified. Requires --from.') do
135
- @options[:input] = $stdin
136
- end
137
-
138
- encoding_option(opts)
139
-
140
- opts.on('--unix-newlines', 'Use Unix-style newlines in written files.',
141
- ('Always true on Unix.' unless Sass::Util.windows?)) do
142
- @options[:unix_newlines] = true if Sass::Util.windows?
143
- end
144
- end
145
-
146
- def miscellaneous(opts)
147
- opts.separator ''
148
- opts.separator 'Miscellaneous:'
149
-
150
- opts.on('--cache-location PATH',
151
- 'The path to save parsed Sass files. Defaults to .sass-cache.') do |loc|
152
- @options[:for_engine][:cache_location] = loc
153
- end
154
-
155
- opts.on('-C', '--no-cache', "Don't cache to sassc files.") do
156
- @options[:for_engine][:read_cache] = false
157
- end
158
-
159
- opts.on('--trace', :NONE, 'Show a full Ruby stack trace on error') do
160
- @options[:trace] = true
161
- end
162
- end
163
-
164
- def process_directory
165
- unless (input = @options[:input] = @args.shift)
166
- raise "Error: directory required when using --recursive."
167
- end
168
-
169
- output = @options[:output] = @args.shift
170
- raise "Error: --from required when using --recursive." unless @options[:from]
171
- raise "Error: --to required when using --recursive." unless @options[:to]
172
- unless File.directory?(@options[:input])
173
- raise "Error: '#{@options[:input]}' is not a directory"
174
- end
175
- if @options[:output] && File.exist?(@options[:output]) &&
176
- !File.directory?(@options[:output])
177
- raise "Error: '#{@options[:output]}' is not a directory"
178
- end
179
- @options[:output] ||= @options[:input]
180
-
181
- if @options[:to] == @options[:from] && !@options[:in_place]
182
- fmt = @options[:from]
183
- raise "Error: converting from #{fmt} to #{fmt} without --in-place"
184
- end
185
-
186
- ext = @options[:from]
187
- Sass::Util.glob("#{@options[:input]}/**/*.#{ext}") do |f|
188
- output =
189
- if @options[:in_place]
190
- f
191
- elsif @options[:output]
192
- output_name = f.gsub(/\.(c|sa|sc|le)ss$/, ".#{@options[:to]}")
193
- output_name[0...@options[:input].size] = @options[:output]
194
- output_name
195
- else
196
- f.gsub(/\.(c|sa|sc|le)ss$/, ".#{@options[:to]}")
197
- end
198
-
199
- unless File.directory?(File.dirname(output))
200
- puts_action :directory, :green, File.dirname(output)
201
- FileUtils.mkdir_p(File.dirname(output))
202
- end
203
- puts_action :convert, :green, f
204
- if File.exist?(output)
205
- puts_action :overwrite, :yellow, output
206
- else
207
- puts_action :create, :green, output
208
- end
209
-
210
- input = open_file(f)
211
- process_file(input, output)
212
- end
213
- end
214
-
215
- def process_file(input, output)
216
- if input.is_a?(File)
217
- @options[:from] ||=
218
- case input.path
219
- when /\.scss$/; :scss
220
- when /\.sass$/; :sass
221
- when /\.less$/; raise "sass-convert no longer supports LessCSS."
222
- when /\.css$/; :css
223
- end
224
- elsif @options[:in_place]
225
- raise "Error: the --in-place option requires a filename."
226
- end
227
-
228
- if output.is_a?(File)
229
- @options[:to] ||=
230
- case output.path
231
- when /\.scss$/; :scss
232
- when /\.sass$/; :sass
233
- end
234
- end
235
-
236
- @options[:from] ||= :css
237
- @options[:to] ||= :sass
238
- @options[:for_engine][:syntax] = @options[:from]
239
-
240
- out =
241
- Sass::Util.silence_sass_warnings do
242
- if @options[:from] == :css
243
- require 'sass/css'
244
- Sass::CSS.new(input.read, @options[:for_tree]).render(@options[:to])
245
- else
246
- if input.is_a?(File)
247
- Sass::Engine.for_file(input.path, @options[:for_engine])
248
- else
249
- Sass::Engine.new(input.read, @options[:for_engine])
250
- end.to_tree.send("to_#{@options[:to]}", @options[:for_tree])
251
- end
252
- end
253
-
254
- output = input.path if @options[:in_place]
255
- write_output(out, output)
256
- rescue Sass::SyntaxError => e
257
- raise e if @options[:trace]
258
- file = " of #{e.sass_filename}" if e.sass_filename
259
- raise "Error on line #{e.sass_line}#{file}: #{e.message}\n Use --trace for backtrace"
260
- rescue LoadError => err
261
- handle_load_error(err)
262
- end
263
- end
264
- end
@@ -1,424 +0,0 @@
1
- module Sass::Exec
2
- # The `sass` and `scss` executables.
3
- class SassScss < Base
4
- attr_reader :default_syntax
5
-
6
- # @param args [Array<String>] The command-line arguments
7
- def initialize(args, default_syntax)
8
- super(args)
9
- @options[:sourcemap] = :auto
10
- @options[:for_engine] = {
11
- :load_paths => default_sass_path
12
- }
13
- @default_syntax = default_syntax
14
- end
15
-
16
- protected
17
-
18
- # Tells optparse how to parse the arguments.
19
- #
20
- # @param opts [OptionParser]
21
- def set_opts(opts)
22
- opts.banner = <<END
23
- Usage: #{default_syntax} [options] [INPUT] [OUTPUT]
24
-
25
- Description:
26
- Converts SCSS or Sass files to CSS.
27
- END
28
-
29
- common_options(opts)
30
- watching_and_updating(opts)
31
- input_and_output(opts)
32
- miscellaneous(opts)
33
- end
34
-
35
- # Processes the options set by the command-line arguments,
36
- # and runs the Sass compiler appropriately.
37
- def process_result
38
- require 'sass'
39
-
40
- if !@options[:update] && !@options[:watch] &&
41
- @args.first && colon_path?(@args.first)
42
- if @args.size == 1
43
- @args = split_colon_path(@args.first)
44
- else
45
- @options[:update] = true
46
- end
47
- end
48
- load_compass if @options[:compass]
49
- return interactive if @options[:interactive]
50
- return watch_or_update if @options[:watch] || @options[:update]
51
- super
52
-
53
- if @options[:sourcemap] != :none && @options[:output_filename]
54
- @options[:sourcemap_filename] = Sass::Util.sourcemap_name(@options[:output_filename])
55
- end
56
-
57
- @options[:for_engine][:filename] = @options[:filename]
58
- @options[:for_engine][:css_filename] = @options[:output] if @options[:output].is_a?(String)
59
- @options[:for_engine][:sourcemap_filename] = @options[:sourcemap_filename]
60
- @options[:for_engine][:sourcemap] = @options[:sourcemap]
61
-
62
- run
63
- end
64
-
65
- private
66
-
67
- def common_options(opts)
68
- opts.separator ''
69
- opts.separator 'Common Options:'
70
-
71
- opts.on('-I', '--load-path PATH', 'Specify a Sass import path.') do |path|
72
- (@options[:for_engine][:load_paths] ||= []) << path
73
- end
74
-
75
- opts.on('-r', '--require LIB', 'Require a Ruby library before running Sass.') do |lib|
76
- require lib
77
- end
78
-
79
- opts.on('--compass', 'Make Compass imports available and load project configuration.') do
80
- @options[:compass] = true
81
- end
82
-
83
- opts.on('-t', '--style NAME', 'Output style. Can be nested (default), compact, ' \
84
- 'compressed, or expanded.') do |name|
85
- @options[:for_engine][:style] = name.to_sym
86
- end
87
-
88
- opts.on("-?", "-h", "--help", "Show this help message.") do
89
- puts opts
90
- exit
91
- end
92
-
93
- opts.on("-v", "--version", "Print the Sass version.") do
94
- puts("Sass #{Sass.version[:string]}")
95
- exit
96
- end
97
- end
98
-
99
- def watching_and_updating(opts)
100
- opts.separator ''
101
- opts.separator 'Watching and Updating:'
102
-
103
- opts.on('--watch', 'Watch files or directories for changes.',
104
- 'The location of the generated CSS can be set using a colon:',
105
- " #{@default_syntax} --watch input.#{@default_syntax}:output.css",
106
- " #{@default_syntax} --watch input-dir:output-dir") do
107
- @options[:watch] = true
108
- end
109
-
110
- # Polling is used by default on Windows.
111
- unless Sass::Util.windows?
112
- opts.on('--poll', 'Check for file changes manually, rather than relying on the OS.',
113
- 'Only meaningful for --watch.') do
114
- @options[:poll] = true
115
- end
116
- end
117
-
118
- opts.on('--update', 'Compile files or directories to CSS.',
119
- 'Locations are set like --watch.') do
120
- @options[:update] = true
121
- end
122
-
123
- opts.on('-f', '--force', 'Recompile every Sass file, even if the CSS file is newer.',
124
- 'Only meaningful for --update.') do
125
- @options[:force] = true
126
- end
127
-
128
- opts.on('--stop-on-error', 'If a file fails to compile, exit immediately.',
129
- 'Only meaningful for --watch and --update.') do
130
- @options[:stop_on_error] = true
131
- end
132
- end
133
-
134
- def input_and_output(opts)
135
- opts.separator ''
136
- opts.separator 'Input and Output:'
137
-
138
- if @default_syntax == :sass
139
- opts.on('--scss',
140
- 'Use the CSS-superset SCSS syntax.') do
141
- @options[:for_engine][:syntax] = :scss
142
- end
143
- else
144
- opts.on('--sass',
145
- 'Use the indented Sass syntax.') do
146
- @options[:for_engine][:syntax] = :sass
147
- end
148
- end
149
-
150
- # This is optional for backwards-compatibility with Sass 3.3, which didn't
151
- # enable sourcemaps by default and instead used "--sourcemap" to do so.
152
- opts.on(:OPTIONAL, '--sourcemap=TYPE',
153
- 'How to link generated output to the source files.',
154
- ' auto (default): relative paths where possible, file URIs elsewhere',
155
- ' file: always absolute file URIs',
156
- ' inline: include the source text in the sourcemap',
157
- ' none: no sourcemaps') do |type|
158
- if type && !%w[auto file inline none].include?(type)
159
- $stderr.puts "Unknown sourcemap type #{type}.\n\n"
160
- $stderr.puts opts
161
- exit
162
- elsif type.nil?
163
- Sass::Util.sass_warn <<MESSAGE.rstrip
164
- DEPRECATION WARNING: Passing --sourcemap without a value is deprecated.
165
- Sourcemaps are now generated by default, so this flag has no effect.
166
- MESSAGE
167
- end
168
-
169
- @options[:sourcemap] = (type || :auto).to_sym
170
- end
171
-
172
- opts.on('-s', '--stdin', :NONE,
173
- 'Read input from standard input instead of an input file.',
174
- 'This is the default if no input file is specified.') do
175
- @options[:input] = $stdin
176
- end
177
-
178
- encoding_option(opts)
179
-
180
- opts.on('--unix-newlines', 'Use Unix-style newlines in written files.',
181
- ('Always true on Unix.' unless Sass::Util.windows?)) do
182
- @options[:unix_newlines] = true if Sass::Util.windows?
183
- end
184
-
185
- opts.on('-g', '--debug-info',
186
- 'Emit output that can be used by the FireSass Firebug plugin.') do
187
- @options[:for_engine][:debug_info] = true
188
- end
189
-
190
- opts.on('-l', '--line-numbers', '--line-comments',
191
- 'Emit comments in the generated CSS indicating the corresponding source line.') do
192
- @options[:for_engine][:line_numbers] = true
193
- end
194
- end
195
-
196
- def miscellaneous(opts)
197
- opts.separator ''
198
- opts.separator 'Miscellaneous:'
199
-
200
- opts.on('-i', '--interactive',
201
- 'Run an interactive SassScript shell.') do
202
- @options[:interactive] = true
203
- end
204
-
205
- opts.on('-c', '--check', "Just check syntax, don't evaluate.") do
206
- require 'stringio'
207
- @options[:check_syntax] = true
208
- @options[:output] = StringIO.new
209
- end
210
-
211
- opts.on('--precision NUMBER_OF_DIGITS', Integer,
212
- "How many digits of precision to use when outputting decimal numbers.",
213
- "Defaults to #{Sass::Script::Value::Number.precision}.") do |precision|
214
- Sass::Script::Value::Number.precision = precision
215
- end
216
-
217
- opts.on('--cache-location PATH',
218
- 'The path to save parsed Sass files. Defaults to .sass-cache.') do |loc|
219
- @options[:for_engine][:cache_location] = loc
220
- end
221
-
222
- opts.on('-C', '--no-cache', "Don't cache parsed Sass files.") do
223
- @options[:for_engine][:cache] = false
224
- end
225
-
226
- opts.on('--trace', :NONE, 'Show a full Ruby stack trace on error.') do
227
- @options[:trace] = true
228
- end
229
-
230
- opts.on('-q', '--quiet', 'Silence warnings and status messages during compilation.') do
231
- @options[:for_engine][:quiet] = true
232
- end
233
- end
234
-
235
- def load_compass
236
- begin
237
- require 'compass'
238
- rescue LoadError
239
- require 'rubygems'
240
- begin
241
- require 'compass'
242
- rescue LoadError
243
- puts "ERROR: Cannot load compass."
244
- exit 1
245
- end
246
- end
247
- Compass.add_project_configuration
248
- Compass.configuration.project_path ||= Dir.pwd
249
- @options[:for_engine][:load_paths] ||= []
250
- @options[:for_engine][:load_paths] += Compass.configuration.sass_load_paths
251
- end
252
-
253
- def interactive
254
- require 'sass/repl'
255
- Sass::Repl.new(@options).run
256
- end
257
-
258
- # @comment
259
- # rubocop:disable MethodLength
260
- def watch_or_update
261
- require 'sass/plugin'
262
- Sass::Plugin.options.merge! @options[:for_engine]
263
- Sass::Plugin.options[:unix_newlines] = @options[:unix_newlines]
264
- Sass::Plugin.options[:poll] = @options[:poll]
265
- Sass::Plugin.options[:sourcemap] = @options[:sourcemap]
266
-
267
- if @options[:force]
268
- raise "The --force flag may only be used with --update." unless @options[:update]
269
- Sass::Plugin.options[:always_update] = true
270
- end
271
-
272
- raise <<MSG if @args.empty?
273
- What files should I watch? Did you mean something like:
274
- #{@default_syntax} --watch input.#{@default_syntax}:output.css
275
- #{@default_syntax} --watch input-dir:output-dir
276
- MSG
277
-
278
- if !colon_path?(@args[0]) && probably_dest_dir?(@args[1])
279
- flag = @options[:update] ? "--update" : "--watch"
280
- err =
281
- if !File.exist?(@args[1])
282
- "doesn't exist"
283
- elsif @args[1] =~ /\.css$/
284
- "is a CSS file"
285
- end
286
- raise <<MSG if err
287
- File #{@args[1]} #{err}.
288
- Did you mean: #{@default_syntax} #{flag} #{@args[0]}:#{@args[1]}
289
- MSG
290
- end
291
-
292
- dirs, files = @args.map {|name| split_colon_path(name)}.
293
- partition {|i, _| File.directory? i}
294
- files.map! do |from, to|
295
- to ||= from.gsub(/\.[^.]*?$/, '.css')
296
- sourcemap = Sass::Util.sourcemap_name(to) if @options[:sourcemap]
297
- [from, to, sourcemap]
298
- end
299
- dirs.map! {|from, to| [from, to || from]}
300
- Sass::Plugin.options[:template_location] = dirs
301
-
302
- Sass::Plugin.on_updated_stylesheet do |_, css, sourcemap|
303
- [css, sourcemap].each do |file|
304
- next unless file
305
- puts_action :write, :green, file
306
- end
307
- end
308
-
309
- had_error = false
310
- Sass::Plugin.on_creating_directory {|dirname| puts_action :directory, :green, dirname}
311
- Sass::Plugin.on_deleting_css {|filename| puts_action :delete, :yellow, filename}
312
- Sass::Plugin.on_deleting_sourcemap {|filename| puts_action :delete, :yellow, filename}
313
- Sass::Plugin.on_compilation_error do |error, _, _|
314
- if error.is_a?(SystemCallError) && !@options[:stop_on_error]
315
- had_error = true
316
- puts_action :error, :red, error.message
317
- STDOUT.flush
318
- next
319
- end
320
-
321
- raise error unless error.is_a?(Sass::SyntaxError) && !@options[:stop_on_error]
322
- had_error = true
323
- puts_action :error, :red,
324
- "#{error.sass_filename} (Line #{error.sass_line}: #{error.message})"
325
- STDOUT.flush
326
- end
327
-
328
- if @options[:update]
329
- Sass::Plugin.update_stylesheets(files)
330
- exit 1 if had_error
331
- return
332
- end
333
-
334
- puts ">>> Sass is watching for changes. Press Ctrl-C to stop."
335
-
336
- Sass::Plugin.on_template_modified do |template|
337
- puts ">>> Change detected to: #{template}"
338
- STDOUT.flush
339
- end
340
- Sass::Plugin.on_template_created do |template|
341
- puts ">>> New template detected: #{template}"
342
- STDOUT.flush
343
- end
344
- Sass::Plugin.on_template_deleted do |template|
345
- puts ">>> Deleted template detected: #{template}"
346
- STDOUT.flush
347
- end
348
-
349
- Sass::Plugin.watch(files)
350
- end
351
- # @comment
352
- # rubocop:enable MethodLength
353
-
354
- def run
355
- input = @options[:input]
356
- output = @options[:output]
357
-
358
- @options[:for_engine][:syntax] ||= :scss if input.is_a?(File) && input.path =~ /\.scss$/
359
- @options[:for_engine][:syntax] ||= @default_syntax
360
- engine =
361
- if input.is_a?(File) && !@options[:check_syntax]
362
- Sass::Engine.for_file(input.path, @options[:for_engine])
363
- else
364
- # We don't need to do any special handling of @options[:check_syntax] here,
365
- # because the Sass syntax checking happens alongside evaluation
366
- # and evaluation doesn't actually evaluate any code anyway.
367
- Sass::Engine.new(input.read, @options[:for_engine])
368
- end
369
-
370
- input.close if input.is_a?(File)
371
-
372
- if @options[:sourcemap] != :none && @options[:sourcemap_filename]
373
- relative_sourcemap_path = Sass::Util.pathname(@options[:sourcemap_filename]).
374
- relative_path_from(Sass::Util.pathname(@options[:output_filename]).dirname)
375
- rendered, mapping = engine.render_with_sourcemap(relative_sourcemap_path.to_s)
376
- write_output(rendered, output)
377
- write_output(mapping.to_json(
378
- :type => @options[:sourcemap],
379
- :css_path => @options[:output_filename],
380
- :sourcemap_path => @options[:sourcemap_filename]) + "\n",
381
- @options[:sourcemap_filename])
382
- else
383
- write_output(engine.render, output)
384
- end
385
- rescue Sass::SyntaxError => e
386
- write_output(Sass::SyntaxError.exception_to_css(e), output) if output.is_a?(String)
387
- raise e if @options[:trace]
388
- raise e.sass_backtrace_str("standard input")
389
- ensure
390
- output.close if output.is_a? File
391
- end
392
-
393
- def colon_path?(path)
394
- !split_colon_path(path)[1].nil?
395
- end
396
-
397
- def split_colon_path(path)
398
- one, two = path.split(':', 2)
399
- if one && two && Sass::Util.windows? &&
400
- one =~ /\A[A-Za-z]\Z/ && two =~ /\A[\/\\]/
401
- # If we're on Windows and we were passed a drive letter path,
402
- # don't split on that colon.
403
- one2, two = two.split(':', 2)
404
- one = one + ':' + one2
405
- end
406
- return one, two
407
- end
408
-
409
- # Whether path is likely to be meant as the destination
410
- # in a source:dest pair.
411
- def probably_dest_dir?(path)
412
- return false unless path
413
- return false if colon_path?(path)
414
- Sass::Util.glob(File.join(path, "*.s[ca]ss")).empty?
415
- end
416
-
417
- def default_sass_path
418
- return unless ENV['SASS_PATH']
419
- # The select here prevents errors when the environment's
420
- # load paths specified do not exist.
421
- ENV['SASS_PATH'].split(File::PATH_SEPARATOR).select {|d| File.directory?(d)}
422
- end
423
- end
424
- end