sass 3.3.0.alpha.16 → 3.3.0.alpha.50

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.
data/REVISION CHANGED
@@ -1 +1 @@
1
- 83d6e352af4861f6c8fe852aaee38ca0097b1d9e
1
+ c962fa1b7d90fdb2e9df72ae2527a48f1f770276
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.3.0.alpha.16
1
+ 3.3.0.alpha.50
data/VERSION_DATE CHANGED
@@ -1 +1 @@
1
- 10 November 2012 01:58:43 GMT
1
+ 29 November 2012 19:00:24 GMT
data/lib/sass/engine.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  require 'set'
2
2
  require 'digest/sha1'
3
3
  require 'sass/cache_stores'
4
+ require 'sass/source/position'
5
+ require 'sass/source/range'
6
+ require 'sass/source/map'
4
7
  require 'sass/tree/node'
5
8
  require 'sass/tree/root_node'
6
9
  require 'sass/tree/rule_node'
@@ -259,9 +262,23 @@ module Sass
259
262
  # cannot be converted to UTF-8
260
263
  # @raise [ArgumentError] if the document uses an unknown encoding with `@charset`
261
264
  def render
262
- return _render unless @options[:quiet]
263
- Sass::Util.silence_sass_warnings {_render}
265
+ return encode_and_set_charset(_to_tree.render) unless @options[:quiet]
266
+ Sass::Util.silence_sass_warnings {encode_and_set_charset(_to_tree.render)}
264
267
  end
268
+
269
+ # Render the template to CSS and return the source map.
270
+ #
271
+ # @param sourcemap_uri [String] The sourcemap URI to use in the @sourceMappingURL comment
272
+ # @return [(String, Sass::Source::Map)] The rendered CSS and the associated source map
273
+ # @raise [Sass::SyntaxError] if there's an error in the document
274
+ # @raise [Encoding::UndefinedConversionError] if the source encoding
275
+ # cannot be converted to UTF-8
276
+ # @raise [ArgumentError] if the document uses an unknown encoding with `@charset`
277
+ def render_with_sourcemap(sourcemap_uri)
278
+ return _render_with_sourcemap(sourcemap_uri) unless @options[:quiet]
279
+ Sass::Util.silence_sass_warnings {_render_with_sourcemap(sourcemap_uri)}
280
+ end
281
+
265
282
  alias_method :to_css, :render
266
283
 
267
284
  # Parses the document into its parse tree. Memoized.
@@ -311,8 +328,19 @@ module Sass
311
328
 
312
329
  private
313
330
 
314
- def _render
315
- rendered = _to_tree.render
331
+ def _render_with_sourcemap(sourcemap_uri)
332
+ rendered, sourcemap = _to_tree.render_with_sourcemap
333
+ compressed = @options[:style] == :compressed
334
+ rendered << "\n" if rendered[-1] != ?\n
335
+ rendered << "\n" unless compressed
336
+ rendered << "/*@ sourceMappingURL="
337
+ rendered << URI.encode(sourcemap_uri)
338
+ rendered << " */"
339
+ rendered = encode_and_set_charset(rendered)
340
+ return rendered, sourcemap
341
+ end
342
+
343
+ def encode_and_set_charset(rendered)
316
344
  return rendered if ruby1_8?
317
345
  begin
318
346
  # Try to convert the result to the original encoding,
@@ -424,7 +452,7 @@ END
424
452
  raise SyntaxError.new(message, :line => index)
425
453
  end
426
454
 
427
- lines << Line.new(line.strip, line_tabs, index, tab_str.size, @options[:filename], [])
455
+ lines << Line.new(line.strip, line_tabs, index, line_tab_str.size, @options[:filename], [])
428
456
  end
429
457
  lines
430
458
  end
@@ -468,6 +496,7 @@ MSG
468
496
 
469
497
  def build_tree(parent, line, root = false)
470
498
  @line = line.index
499
+ @offset = line.offset
471
500
  node_or_nodes = parse_line(parent, line, root)
472
501
 
473
502
  Array(node_or_nodes).each do |node|
@@ -553,10 +582,23 @@ WARNING
553
582
  # if we're using the new property syntax
554
583
  Tree::RuleNode.new(parse_interp(line.text))
555
584
  else
585
+ name_start_offset = line.offset + 1 # +1 for the leading ':'
556
586
  name, value = line.text.scan(PROPERTY_OLD)[0]
557
587
  raise SyntaxError.new("Invalid property: \"#{line.text}\".",
558
588
  :line => @line) if name.nil? || value.nil?
559
- parse_property(name, parse_interp(name), value, :old, line)
589
+
590
+ value_start_offset = name_end_offset = name_start_offset + name.length
591
+ if !value.empty?
592
+ # +1 and -1 both compensate for the leading ':', which is part of line.text
593
+ value_start_offset = name_start_offset + line.text.index(value, name.length + 1) - 1
594
+ end
595
+
596
+ property = parse_property(name, parse_interp(name), value, :old, line, value_start_offset)
597
+ property.name_source_range = Sass::Source::Range.new(
598
+ Sass::Source::Position.new(@line, to_parser_offset(name_start_offset)),
599
+ Sass::Source::Position.new(@line, to_parser_offset(name_end_offset)),
600
+ @options[:filename])
601
+ property
560
602
  end
561
603
  when ?$
562
604
  parse_variable(line)
@@ -582,32 +624,50 @@ WARNING
582
624
  def parse_property_or_rule(line)
583
625
  scanner = Sass::Util::MultibyteStringScanner.new(line.text)
584
626
  hack_char = scanner.scan(/[:\*\.]|\#(?!\{)/)
585
- parser = Sass::SCSS::Parser.new(scanner, @options[:filename], @line)
627
+ offset = line.offset
628
+ offset += hack_char.length if hack_char
629
+ parser = Sass::SCSS::Parser.new(scanner, @options[:filename], @line, to_parser_offset(offset))
586
630
 
587
631
  unless res = parser.parse_interp_ident
588
- return Tree::RuleNode.new(parse_interp(line.text))
632
+ return Tree::RuleNode.new(parse_interp(line.text, line.offset))
589
633
  end
634
+
635
+ ident_range = Sass::Source::Range.new(
636
+ Sass::Source::Position.new(@line, to_parser_offset(offset)),
637
+ Sass::Source::Position.new(@line, parser.offset),
638
+ @options[:filename])
639
+ offset = parser.offset - 1
590
640
  res.unshift(hack_char) if hack_char
591
641
  if comment = scanner.scan(Sass::SCSS::RX::COMMENT)
592
642
  res << comment
643
+ offset += comment.length
593
644
  end
594
645
 
595
646
  name = line.text[0...scanner.pos]
596
- if scanner.scan(/\s*:(?:\s|$)/)
597
- parse_property(name, res, scanner.rest, :new, line)
647
+ if scanned = scanner.scan(/\s*:(?:\s+|$)/)
648
+ offset += scanned.length
649
+ property = parse_property(name, res, scanner.rest, :new, line, offset)
650
+ property.name_source_range = ident_range
651
+ property
598
652
  else
599
653
  res.pop if comment
600
654
  Tree::RuleNode.new(res + parse_interp(scanner.rest))
601
655
  end
602
656
  end
603
657
 
604
- def parse_property(name, parsed_name, value, prop, line)
658
+ def parse_property(name, parsed_name, value, prop, line, start_offset)
605
659
  if value.strip.empty?
606
660
  expr = Sass::Script::String.new("")
661
+ end_offset = start_offset
607
662
  else
608
- expr = parse_script(value, :offset => line.offset + line.text.index(value))
663
+ expr = parse_script(value, :offset => to_parser_offset(start_offset))
664
+ end_offset = expr.source_range.end_pos.offset - 1
609
665
  end
610
666
  node = Tree::PropNode.new(parse_interp(name), expr, prop)
667
+ node.value_source_range = Sass::Source::Range.new(
668
+ Sass::Source::Position.new(line.index, to_parser_offset(start_offset)),
669
+ Sass::Source::Position.new(line.index, to_parser_offset(end_offset)),
670
+ @options[:filename])
611
671
  if value.strip.empty? && line.children.empty?
612
672
  raise SyntaxError.new(
613
673
  "Invalid property: \"#{node.declaration}\" (no value)." +
@@ -624,7 +684,12 @@ WARNING
624
684
  raise SyntaxError.new("Invalid variable: \"#{line.text}\".",
625
685
  :line => @line) unless name && value
626
686
 
627
- expr = parse_script(value, :offset => line.offset + line.text.index(value))
687
+ # This workaround is needed for the case when the variable value is part of the identifier,
688
+ # otherwise we end up with the offset equal to the value index inside the name:
689
+ # $red_color: red;
690
+ var_lhs_length = 1 + name.length # 1 stands for '$'
691
+ index = line.text.index(value, line.offset + var_lhs_length) || 0
692
+ expr = parse_script(value, :offset => to_parser_offset(line.offset + index))
628
693
 
629
694
  Tree::VariableNode.new(name, expr, default)
630
695
  end
@@ -636,7 +701,8 @@ WARNING
636
701
  if silent
637
702
  value = [line.text]
638
703
  else
639
- value = self.class.parse_interp(line.text, line.index, line.offset, :filename => @filename)
704
+ value = self.class.parse_interp(
705
+ line.text, line.index, to_parser_offset(line.offset), :filename => @filename)
640
706
  value[0].slice!(2) if loud # get rid of the "!"
641
707
  end
642
708
  value = with_extracted_values(value) do |str|
@@ -711,7 +777,7 @@ WARNING
711
777
  :line => @line + 1) unless line.children.empty?
712
778
  Tree::CharsetNode.new(name)
713
779
  when 'media'
714
- parser = Sass::SCSS::Parser.new(value, @options[:filename], @line)
780
+ parser = Sass::SCSS::Parser.new(value, @options[:filename], @line, to_parser_offset(@offset))
715
781
  Tree::MediaNode.new(parser.parse_media_query_list.to_a)
716
782
  else
717
783
  Tree::DirectiveNode.new(
@@ -802,29 +868,61 @@ WARNING
802
868
  def parse_import_arg(scanner, offset)
803
869
  return if scanner.eos?
804
870
 
805
- if scanner.match?(/url\(/i)
806
- script_parser = Sass::Script::Parser.new(scanner, @line, offset, @options)
871
+ if match_length = scanner.match?(/url\(/i)
872
+ script_parser = Sass::Script::Parser.new(scanner, @line, to_parser_offset(offset), @options)
807
873
  str = script_parser.parse_string
808
- media_parser = Sass::SCSS::Parser.new(scanner, @options[:filename], @line)
809
- media = media_parser.parse_media_query_list
810
- return Tree::CssImportNode.new(str, media.to_a)
874
+
875
+ media_parser = Sass::SCSS::Parser.new(scanner, @options[:filename], @line, str.source_range.end_pos.offset)
876
+ if media = media_parser.parse_media_query_list
877
+ end_pos = Sass::Source::Position.new(@line, media_parser.offset + 1)
878
+ node = Tree::CssImportNode.new(str, media.to_a)
879
+ else
880
+ end_pos = str.source_range.end_pos
881
+ node = Tree::CssImportNode.new(str)
882
+ end
883
+
884
+ node.source_range = Sass::Source::Range.new(str.source_range.start_pos, end_pos, @options[:filename])
885
+ return node
811
886
  end
812
887
 
813
888
  unless str = scanner.scan(Sass::SCSS::RX::STRING)
814
- return Tree::ImportNode.new(scanner.scan(/[^,;]+/))
889
+ scanned = scanner.scan(/[^,;]+/)
890
+ node = Tree::ImportNode.new(scanned)
891
+ start_parser_offset = to_parser_offset(offset)
892
+ node.source_range = Sass::Source::Range.new(
893
+ Sass::Source::Position.new(@line, start_parser_offset),
894
+ Sass::Source::Position.new(@line, start_parser_offset + scanned.length),
895
+ @options[:filename])
896
+ return node
815
897
  end
816
898
 
899
+ start_offset = offset
900
+ offset += str.length
817
901
  val = scanner[1] || scanner[2]
818
- scanner.scan(/\s*/)
902
+ scanned = scanner.scan(/\s*/)
819
903
  if !scanner.match?(/[,;]|$/)
820
- media_parser = Sass::SCSS::Parser.new(scanner, @options[:filename], @line)
904
+ offset += scanned.length if scanned
905
+ media_parser = Sass::SCSS::Parser.new(scanner, @options[:filename], @line, offset)
821
906
  media = media_parser.parse_media_query_list
822
- Tree::CssImportNode.new(str || uri, media.to_a)
907
+ node = Tree::CssImportNode.new(str || uri, media.to_a)
908
+ node.source_range = Sass::Source::Range.new(
909
+ Sass::Source::Position.new(@line, to_parser_offset(start_offset)),
910
+ Sass::Source::Position.new(@line, media_parser.offset),
911
+ @options[:filename])
823
912
  elsif val =~ /^(https?:)?\/\//
824
- Tree::CssImportNode.new("url(#{val})")
913
+ node = Tree::CssImportNode.new("url(#{val})")
914
+ node.source_range = Sass::Source::Range.new(
915
+ Sass::Source::Position.new(@line, to_parser_offset(start_offset)),
916
+ Sass::Source::Position.new(@line, to_parser_offset(offset)),
917
+ @options[:filename])
825
918
  else
826
- Tree::ImportNode.new(val)
919
+ node = Tree::ImportNode.new(val)
920
+ node.source_range = Sass::Source::Range.new(
921
+ Sass::Source::Position.new(@line, to_parser_offset(start_offset)),
922
+ Sass::Source::Position.new(@line, to_parser_offset(offset)),
923
+ @options[:filename])
827
924
  end
925
+ node
828
926
  end
829
927
 
830
928
  MIXIN_DEF_RE = /^(?:=|@mixin)\s*(#{Sass::SCSS::RX::IDENT})(.*)$/
@@ -833,7 +931,7 @@ WARNING
833
931
  raise SyntaxError.new("Invalid mixin \"#{line.text[1..-1]}\".") if name.nil?
834
932
 
835
933
  offset = line.offset + line.text.size - arg_string.size
836
- args, splat = Script::Parser.new(arg_string.strip, @line, offset, @options).
934
+ args, splat = Script::Parser.new(arg_string.strip, @line, to_parser_offset(offset), @options).
837
935
  parse_mixin_definition_arglist
838
936
  Tree::MixinDefNode.new(name, args, splat)
839
937
  end
@@ -853,7 +951,7 @@ WARNING
853
951
  raise SyntaxError.new("Invalid mixin include \"#{line.text}\".") if name.nil?
854
952
 
855
953
  offset = line.offset + line.text.size - arg_string.size
856
- args, keywords, splat = Script::Parser.new(arg_string.strip, @line, offset, @options).
954
+ args, keywords, splat = Script::Parser.new(arg_string.strip, @line, to_parser_offset(offset), @options).
857
955
  parse_mixin_include_arglist
858
956
  Tree::MixinNode.new(name, args, keywords, splat)
859
957
  end
@@ -864,14 +962,14 @@ WARNING
864
962
  raise SyntaxError.new("Invalid function definition \"#{line.text}\".") if name.nil?
865
963
 
866
964
  offset = line.offset + line.text.size - arg_string.size
867
- args, splat = Script::Parser.new(arg_string.strip, @line, offset, @options).
965
+ args, splat = Script::Parser.new(arg_string.strip, @line, to_parser_offset(offset), @options).
868
966
  parse_function_definition_arglist
869
967
  Tree::FunctionNode.new(name, args, splat)
870
968
  end
871
969
 
872
970
  def parse_script(script, options = {})
873
971
  line = options[:line] || @line
874
- offset = options[:offset] || 0
972
+ offset = options[:offset] || @offset + 1
875
973
  Script.parse(script, line, offset, @options)
876
974
  end
877
975
 
@@ -899,6 +997,11 @@ WARNING
899
997
  self.class.parse_interp(text, @line, offset, :filename => @filename)
900
998
  end
901
999
 
1000
+ # Parser tracks 1-based line and offset, so our offset should be converted.
1001
+ def to_parser_offset(offset)
1002
+ offset + 1
1003
+ end
1004
+
902
1005
  # It's important that this have strings (at least)
903
1006
  # at the beginning, the end, and between each Script::Node.
904
1007
  #
@@ -912,8 +1015,9 @@ WARNING
912
1015
  res << "\\" * (escapes - 1) << '#{'
913
1016
  else
914
1017
  res << "\\" * [0, escapes - 1].max
1018
+ # Add 1 to emulate to_parser_offset.
915
1019
  res << Script::Parser.new(
916
- scan, line, offset + scan.pos - scan.matched_size, options).
1020
+ scan, line, offset + scan.pos - scan.matched_size + 1, options).
917
1021
  parse_interpolated
918
1022
  end
919
1023
  end
data/lib/sass/exec.rb CHANGED
@@ -95,6 +95,7 @@ module Sass
95
95
 
96
96
  # Processes the options set by the command-line arguments.
97
97
  # In particular, sets `@options[:input]` and `@options[:output]`
98
+ # (and `@options[:sourcemap]` if one has been specified)
98
99
  # to appropriate IO streams.
99
100
  #
100
101
  # This is meant to be overridden by subclasses
@@ -108,7 +109,13 @@ module Sass
108
109
  @options[:filename] = filename
109
110
  open_file(filename) || $stdin
110
111
  end
111
- output ||= open_file(args.shift, 'w') || $stdout
112
+ @options[:output_filename] = args.shift
113
+ output ||= open_file(@options[:output_filename], 'w') || $stdout
114
+
115
+ if @options[:sourcemap] && @options[:output_filename]
116
+ @options[:sourcemap_filename] = Util::sourcemap_name(@options[:output_filename])
117
+ @options[:sourcemap] = open_file(@options[:sourcemap_filename], 'w')
118
+ end
112
119
 
113
120
  @options[:input], @options[:output] = input, output
114
121
  end
@@ -281,6 +288,9 @@ END
281
288
  opts.on('-C', '--no-cache', "Don't cache to sassc files.") do
282
289
  @options[:for_engine][:cache] = false
283
290
  end
291
+ opts.on('--sourcemap', 'Create sourcemap files next to the generated CSS files.') do
292
+ @options[:sourcemap] = true
293
+ end
284
294
 
285
295
  unless ::Sass::Util.ruby1_8?
286
296
  opts.on('-E encoding', 'Specify the default encoding for Sass files.') do |encoding|
@@ -311,6 +321,7 @@ END
311
321
  begin
312
322
  input = @options[:input]
313
323
  output = @options[:output]
324
+ sourcemap = @options[:sourcemap]
314
325
 
315
326
  @options[:for_engine][:syntax] ||= :scss if input.is_a?(File) && input.path =~ /\.scss$/
316
327
  @options[:for_engine][:syntax] ||= @default_syntax
@@ -326,11 +337,21 @@ END
326
337
 
327
338
  input.close() if input.is_a?(File)
328
339
 
329
- output.write(engine.render)
330
- output.close() if output.is_a? File
340
+ if sourcemap.is_a? File
341
+ relative_sourcemap_path = Pathname.new(@options[:sourcemap_filename]).
342
+ relative_path_from(Pathname.new(@options[:output_filename]).dirname)
343
+ rendered, mapping = engine.render_with_sourcemap(relative_sourcemap_path.to_s)
344
+ output.write(rendered)
345
+ sourcemap.puts(mapping.to_json(@options[:output_filename]))
346
+ else
347
+ output.write(engine.render)
348
+ end
331
349
  rescue ::Sass::SyntaxError => e
332
350
  raise e if @options[:trace]
333
351
  raise e.sass_backtrace_str("standard input")
352
+ ensure
353
+ output.close if output.is_a? File
354
+ sourcemap.close if sourcemap.is_a? File
334
355
  end
335
356
  end
336
357
 
@@ -363,6 +384,7 @@ END
363
384
  ::Sass::Plugin.options.merge! @options[:for_engine]
364
385
  ::Sass::Plugin.options[:unix_newlines] = @options[:unix_newlines]
365
386
  ::Sass::Plugin.options[:poll] = @options[:poll]
387
+ ::Sass::Plugin.options[:sourcemap] = @options[:sourcemap]
366
388
 
367
389
  if @options[:force]
368
390
  raise "The --force flag may only be used with --update." unless @options[:update]
@@ -391,15 +413,22 @@ MSG
391
413
 
392
414
  dirs, files = @args.map {|name| split_colon_path(name)}.
393
415
  partition {|i, _| File.directory? i}
394
- files.map! {|from, to| [from, to || from.gsub(/\.[^.]*?$/, '.css')]}
416
+ files.map! do |from, to|
417
+ to ||= from.gsub(/\.[^.]*?$/, '.css')
418
+ sourcemap = Util::sourcemap_name(to) if @options[:sourcemap]
419
+ [from, to, sourcemap]
420
+ end
395
421
  dirs.map! {|from, to| [from, to || from]}
396
422
  ::Sass::Plugin.options[:template_location] = dirs
397
423
 
398
- ::Sass::Plugin.on_updated_stylesheet do |_, css|
399
- if File.exists? css
400
- puts_action :overwrite, :yellow, css
401
- else
402
- puts_action :create, :green, css
424
+ ::Sass::Plugin.on_updated_stylesheet do |_, css, sourcemap|
425
+ [css, sourcemap].each do |file|
426
+ next unless file
427
+ if File.exists? file
428
+ puts_action :overwrite, :yellow, file
429
+ else
430
+ puts_action :create, :green, file
431
+ end
403
432
  end
404
433
  end
405
434
 
@@ -65,6 +65,8 @@ module Sass::Plugin
65
65
  # The location of the Sass/SCSS file being updated.
66
66
  # @yieldparam css [String]
67
67
  # The location of the CSS file being generated.
68
+ # @yieldparam sourcemap [String]
69
+ # The location of the sourcemap being generated, if any.
68
70
  define_callback :updated_stylesheet
69
71
 
70
72
  # Register a callback to be run before a single stylesheet is updated.
@@ -81,6 +83,8 @@ module Sass::Plugin
81
83
  # The location of the Sass/SCSS file being updated.
82
84
  # @yieldparam css [String]
83
85
  # The location of the CSS file being generated.
86
+ # @yieldparam sourcemap [String]
87
+ # The location of the sourcemap file being generated, if any.
84
88
  define_callback :updating_stylesheet
85
89
 
86
90
  def on_updating_stylesheet_with_deprecation_warning(&block)
@@ -192,17 +196,19 @@ module Sass::Plugin
192
196
  # Get the relative path to the file
193
197
  name = file.sub(template_location.to_s.sub(/\/*$/, '/'), "")
194
198
  css = css_filename(name, css_location)
195
- individual_files << [file, css]
199
+ sourcemap = Util::sourcemap_name(css) if engine_options[:sourcemap]
200
+ individual_files << [file, css, sourcemap]
196
201
  end
197
202
  end
198
203
 
199
204
  run_updating_stylesheets individual_files
200
205
 
201
- individual_files.each do |file, css|
206
+ individual_files.each do |file, css, sourcemap|
207
+ # TODO: Does staleness_checker need to check the sourcemap file as well?
202
208
  if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
203
- update_stylesheet(file, css)
209
+ update_stylesheet(file, css, sourcemap)
204
210
  else
205
- run_not_updating_stylesheet(file, css)
211
+ run_not_updating_stylesheet(file, css, sourcemap)
206
212
  end
207
213
  end
208
214
  end
@@ -328,7 +334,7 @@ module Sass::Plugin
328
334
 
329
335
  private
330
336
 
331
- def update_stylesheet(filename, css)
337
+ def update_stylesheet(filename, css, sourcemap)
332
338
  dir = File.dirname(css)
333
339
  unless File.exists?(dir)
334
340
  run_creating_directory dir
@@ -338,23 +344,30 @@ module Sass::Plugin
338
344
  begin
339
345
  File.read(filename) unless File.readable?(filename) # triggers an error for handling
340
346
  engine_opts = engine_options(:css_filename => css, :filename => filename)
341
- result = Sass::Engine.for_file(filename, engine_opts).render
347
+ mapping = nil
348
+ engine = Sass::Engine.for_file(filename, engine_opts)
349
+ if sourcemap
350
+ rendered, mapping = engine.render_with_sourcemap(File.basename(sourcemap))
351
+ else
352
+ rendered = engine.render
353
+ end
342
354
  rescue Exception => e
343
355
  compilation_error_occured = true
344
- run_compilation_error e, filename, css
345
- result = Sass::SyntaxError.exception_to_css(e, options)
356
+ run_compilation_error e, filename, css, sourcemap
357
+ rendered = Sass::SyntaxError.exception_to_css(e, options)
346
358
  else
347
- run_updating_stylesheet filename, css
359
+ run_updating_stylesheet filename, css, sourcemap
348
360
  end
349
361
 
350
- write_file(css, result)
351
- run_updated_stylesheet(filename, css) unless compilation_error_occured
362
+ write_file(css, rendered)
363
+ write_file(sourcemap, mapping.to_json(css)) if mapping
364
+ run_updated_stylesheet(filename, css, sourcemap) unless compilation_error_occured
352
365
  end
353
366
 
354
- def write_file(css, content)
367
+ def write_file(fileName, content)
355
368
  flag = 'w'
356
369
  flag = 'wb' if Sass::Util.windows? && options[:unix_newlines]
357
- File.open(css, flag) do |file|
370
+ File.open(fileName, flag) do |file|
358
371
  file.set_encoding(content.encoding) unless Sass::Util.ruby1_8?
359
372
  file.print(content)
360
373
  end