hardpixel/marv

View on GitHub
lib/marv/project/builder/assets.rb

Summary

Maintainability
A
2 hrs
Test Coverage
require 'sprockets'
require 'autoprefixer-rails'

module Marv
  module Project
    class Assets

      # Initialize assets builder
      def initialize(builder)
        @builder = builder
        @task = builder.task
        @project = builder.project
        @config = builder.project.config

        init_sprockets
      end

      # Clean images
      def clean_images
        @task.shell.mute do
          # Remove screenshot image
          ::Dir.glob(::File.join(@project.build_path, 'screenshot.*')).each do |file|
            @task.remove_file file
          end

          # Remove images folder
          @task.remove_dir ::File.join(@project.build_path, 'images')
        end
      end

      # Copy images
      def copy_images
        @task.shell.mute do
          ::Dir.glob(::File.join(@project.assets_path, 'images', '*')).each do |filename|
            # Check for screenshot and move it into main build directory
            if filename.index(/screenshot/)
              @task.copy_file filename, ::File.join(@project.build_path, ::File.basename(filename)), :force => true
            else
              # Copy the other files in images directory
              @task.copy_file filename, ::File.join(@project.build_path, 'images', ::File.basename(filename)), :force => true
            end
          end
        end
      end

      # Build assets
      def build_assets
        @project.assets.each do |asset|
          # Catch any sprockets errors and continue the process
          begin
            build_asset_file asset
          rescue Exception => e
            print_asset_error asset, e.message
          end
        end
      end

      # Build asset file
      def build_asset_file(asset)
        destination = ::File.join(@project.build_path, asset)

        @task.shell.mute do
          sprocket = @sprockets.find_asset(asset.last)
          # Create asset destination
          @task.empty_directory ::File.dirname(destination) unless ::File.directory?(::File.dirname(destination))
          # Write file to destination
          sprocket.write_to(destination) unless sprocket.nil?
        end
      end

      # Print error to screen and file
      def print_asset_error(asset, message)
        destination = ::File.join(@project.build_path, asset)

        @task.say_error "Error while building #{asset.last}:", message

        @task.shell.mute do
          @task.create_file destination unless ::File.exists?(destination)
          @task.append_to_file destination, message
        end
      end

      # Init sprockets
      def init_sprockets
        if ExecJS::Runtimes.runtimes.none?(&:available?)
          @task.say_error "No execjs runtime found! Aborting..."
          abort
        end

        @sprockets   = ::Sprockets::Environment.new
        autoprefixer = @config[:autoprefixer]

        ['javascripts', 'stylesheets'].each do |dir|
          @sprockets.append_path ::File.join(@project.assets_path, dir)
        end

        # Check for js compression
        if @config[:compress_js]
          @sprockets.js_compressor = :uglify
        end

        # Check for css compression
        if @config[:compress_css]
          @sprockets.css_compressor = :scss
        end

        # Passing the @project instance variable to the Sprockets::Context instance
        # used for processing the asset ERB files
        @sprockets.context_class.instance_exec(@project) do |project|
          define_method :config do
            project.config
          end
        end

        unless autoprefixer == false
          runtimes = AutoprefixerRails::Processor::SUPPORTED_RUNTIMES

          if runtimes.any?(&:available?)
            AutoprefixerRails.install(@sprockets, Hash(autoprefixer))
          else
            names = runtimes.map(&:name).join(', ')
            @task.say_warning "Autoprefixer disabled: no supported runtime found [ #{names} ]"
          end
        end
      end

    end
  end
end