Class Haml::Exec::SassConvert
In: lib/haml/exec.rb
Parent: Generic

The `sass-convert` executable.

Methods

Public Class methods

@param args [Array<String>] The command-line arguments

[Source]

     # File lib/haml/exec.rb, line 656
656:       def initialize(args)
657:         super
658:         require 'sass'
659:         @options[:for_tree] = {}
660:         @options[:for_engine] = {:cache => false, :read_cache => true}
661:       end

Public Instance methods

Processes the options set by the command-line arguments, and runs the CSS compiler appropriately.

[Source]

     # File lib/haml/exec.rb, line 736
736:       def process_result
737:         require 'sass'
738: 
739:         if @options[:recursive]
740:           process_directory
741:           return
742:         end
743: 
744:         super
745:         input = @options[:input]
746:         raise "Error: '#{input.path}' is a directory (did you mean to use --recursive?)" if File.directory?(input)
747:         output = @options[:output]
748:         output = input if @options[:in_place]
749:         process_file(input, output)
750:       end

Tells optparse how to parse the arguments.

@param opts [OptionParser]

[Source]

     # File lib/haml/exec.rb, line 666
666:       def set_opts(opts)
667:         opts.banner = "Usage: sass-convert [options] [INPUT] [OUTPUT]\n\nDescription:\n  Converts between CSS, Sass, and SCSS files.\n  E.g. converts from SCSS to Sass,\n  or converts from CSS to SCSS (adding appropriate nesting).\n\nOptions:\n"
668: 
669:         opts.on('-F', '--from FORMAT',
670:           'The format to convert from. Can be css, scss, sass, less, or sass2.',
671:           'sass2 is the same as sass, but updates more old syntax to new.',
672:           'By default, this is inferred from the input filename.',
673:           'If there is none, defaults to css.') do |name|
674:           @options[:from] = name.downcase.to_sym
675:           unless [:css, :scss, :sass, :less, :sass2].include?(@options[:from])
676:             raise "Unknown format for sass-convert --from: #{name}"
677:           end
678:           try_less_note if @options[:from] == :less
679:         end
680: 
681:         opts.on('-T', '--to FORMAT',
682:           'The format to convert to. Can be scss or sass.',
683:           'By default, this is inferred from the output filename.',
684:           'If there is none, defaults to sass.') do |name|
685:           @options[:to] = name.downcase.to_sym
686:           unless [:scss, :sass].include?(@options[:to])
687:             raise "Unknown format for sass-convert --to: #{name}"
688:           end
689:         end
690: 
691:         opts.on('-R', '--recursive',
692:           'Convert all the files in a directory. Requires --from and --to.') do
693:           @options[:recursive] = true
694:         end
695: 
696:         opts.on('-i', '--in-place',
697:           'Convert a file to its own syntax.',
698:           'This can be used to update some deprecated syntax.') do
699:           @options[:in_place] = true
700:         end
701: 
702:         opts.on('--dasherize', 'Convert underscores to dashes') do
703:           @options[:for_tree][:dasherize] = true
704:         end
705: 
706:         opts.on('--old', 'Output the old-style ":prop val" property syntax.',
707:                          'Only meaningful when generating Sass.') do
708:           @options[:for_tree][:old] = true
709:         end
710: 
711:         opts.on('-C', '--no-cache', "Don't cache to sassc files.") do
712:           @options[:for_engine][:read_cache] = false
713:         end
714: 
715:         unless ::Haml::Util.ruby1_8?
716:           opts.on('-E encoding', 'Specify the default encoding for Sass and CSS files.') do |encoding|
717:             Encoding.default_external = encoding
718:           end
719:         end
720: 
721:         super
722:       end

Private Instance methods

[Source]

     # File lib/haml/exec.rb, line 754
754:       def process_directory
755:         unless input = @options[:input] = @args.shift
756:           raise "Error: directory required when using --recursive."
757:         end
758: 
759:         output = @options[:output] = @args.shift
760:         raise "Error: --from required when using --recursive." unless @options[:from]
761:         raise "Error: --to required when using --recursive." unless @options[:to]
762:         raise "Error: '#{@options[:input]}' is not a directory" unless File.directory?(@options[:input])
763:         if @options[:output] && File.exists?(@options[:output]) && !File.directory?(@options[:output])
764:           raise "Error: '#{@options[:output]}' is not a directory"
765:         end
766:         @options[:output] ||= @options[:input]
767: 
768:         from = @options[:from]
769:         from = :sass if from == :sass2
770:         if @options[:to] == @options[:from] && !@options[:in_place]
771:           fmt = @options[:from]
772:           raise "Error: converting from #{fmt} to #{fmt} without --in-place"
773:         end
774: 
775:         ext = @options[:from]
776:         ext = :sass if ext == :sass2
777:         Dir.glob("#{@options[:input]}/**/*.#{ext}") do |f|
778:           output =
779:             if @options[:in_place]
780:               f
781:             elsif @options[:output]
782:               output_name = f.gsub(/\.(c|sa|sc|le)ss$/, ".#{@options[:to]}")
783:               output_name[0...@options[:input].size] = @options[:output]
784:               output_name
785:             else
786:               f.gsub(/\.(c|sa|sc|le)ss$/, ".#{@options[:to]}")
787:             end
788: 
789:           unless File.directory?(File.dirname(output))
790:             puts_action :directory, :green, File.dirname(output)
791:             FileUtils.mkdir_p(File.dirname(output))
792:           end
793:           puts_action :convert, :green, f
794:           if File.exists?(output)
795:             puts_action :overwrite, :yellow, output
796:           else
797:             puts_action :create, :green, output
798:           end
799: 
800:           input = open_file(f)
801:           output = @options[:in_place] ? input : open_file(output, "w")
802:           process_file(input, output)
803:         end
804:       end

[Source]

     # File lib/haml/exec.rb, line 806
806:       def process_file(input, output)
807:         if input.is_a?(File)
808:           @options[:from] ||=
809:             case input.path
810:             when /\.scss$/; :scss
811:             when /\.sass$/; :sass
812:             when /\.less$/; :less
813:             when /\.css$/; :css
814:             end
815:         elsif @options[:in_place]
816:           raise "Error: the --in-place option requires a filename."
817:         end
818: 
819:         if output.is_a?(File)
820:           @options[:to] ||=
821:             case output.path
822:             when /\.scss$/; :scss
823:             when /\.sass$/; :sass
824:             end
825:         end
826: 
827:         if @options[:from] == :sass2
828:           @options[:from] = :sass
829:           @options[:for_engine][:sass2] = true
830:         end
831: 
832:         @options[:from] ||= :css
833:         @options[:to] ||= :sass
834:         @options[:for_engine][:syntax] = @options[:from]
835: 
836:         out =
837:           ::Haml::Util.silence_haml_warnings do
838:             if @options[:from] == :css
839:               require 'sass/css'
840:               ::Sass::CSS.new(input.read, @options[:for_tree]).render(@options[:to])
841:             elsif @options[:from] == :less
842:               require 'sass/less'
843:               try_less_note
844:               input = input.read if input.is_a?(IO) && !input.is_a?(File) # Less is dumb
845:               Less::Engine.new(input).to_tree.to_sass_tree.send("to_#{@options[:to]}", @options[:for_tree])
846:             else
847:               if input.is_a?(File)
848:                 ::Sass::Files.tree_for(input.path, @options[:for_engine])
849:               else
850:                 ::Sass::Engine.new(input.read, @options[:for_engine]).to_tree
851:               end.send("to_#{@options[:to]}", @options[:for_tree])
852:             end
853:           end
854: 
855:         output = File.open(input.path, 'w') if @options[:in_place]
856:         output.write(out)
857:       rescue ::Sass::SyntaxError => e
858:         raise e if @options[:trace]
859:         file = " of #{e.sass_filename}" if e.sass_filename
860:         raise "Error on line #{e.sass_line}#{file}: #{e.message}\n  Use --trace for backtrace"
861:       rescue LoadError => err
862:         handle_load_error(err)
863:       end

[Source]

     # File lib/haml/exec.rb, line 866
866:       def try_less_note
867:         return if @@less_note_printed
868:         @@less_note_printed = true
869:         warn "* NOTE: Sass and Less are different languages, and they work differently.\n* I'll do my best to translate, but some features -- especially mixins --\n* should be checked by hand.\n"
870:       end

[Validate]