<commit_before>require 'sprockets'
require 'middleman-core/contracts'
require 'middleman-core/sitemap/resource'

require_relative 'resource'
require_relative 'interface'

module Middleman
  module Sprockets
    class Extension < Extension
      attr_reader :environment,
                  :interface

      expose_to_config   sprockets: :environment
      expose_to_template sprockets: :environment

      option :supported_output_extensions, ['.css', '.js'], 'Output extensions sprockets should process'
      option :imported_asset_path,         'assets',        'Where under source imported assets should be placed.'
      option :expose_middleman_helpers,    false,           'Whether to expose middleman helpers to sprockets.'

      Contract ::Middleman::Application, Hash, Maybe[Proc] => Any
      def initialize app, options_hash={}, &block
        super

        @linked_assets       = Set.new
        @environment         = ::Sprockets::Environment.new
        @interface           = Interface.new options, @environment

        use_sassc_if_available
      end

      Contract Any
      def after_configuration
        @environment.append_path((app.source_dir + app.config[:js_dir]).to_s)
        @environment.append_path((app.source_dir + app.config[:css_dir]).to_s)
        @environment.append_path(app.source_dir.to_s)

        append_paths_from_gems

        the_app = app
        the_env = environment

        @environment.context_class.send(:define_method, :app)  { the_app }
        @environment.context_class.send(:define_method, :data) { the_app.data }
        @environment.context_class.send(:define_method, :env)  { the_env }

        @environment.context_class.class_eval do
          def asset_path path, options={}
            # Handle people calling with the Middleman/Padrino asset path signature
            if path.is_a?(::Symbol) && !options.is_a?(::Hash)
              kind = path
              path = options
            else
              kind = {
                image: :images,
                font: :fonts,
                javascript: :js,
                stylesheet: :css
              }.fetch(options[:type], options[:type])
            end

            if File.extname(path).empty?
              path << { js: '.js', css: '.css' }.fetch(kind, '')
            end

            if app.extensions[:sprockets].check_asset(path)
              app.extensions[:sprockets].sprockets_asset_path(env[path]).sub(/^\/?/, '/')
            else
              app.asset_path(kind, path)
            end
          end
        end

        expose_app_helpers_to_sprockets! if options[:expose_middleman_helpers]
      end

      Contract ResourceList => ResourceList
      def manipulate_resource_list resources
        sprockets_resources, base_resources = resources.partition(&method(:processible?))
        ::Middleman::Util.instrument 'sprockets', name: 'manipulator.sprockets_resources' do
          sprockets_resources.map!(&method(:process_sprockets_resource))
        end

        linked_resources = ::Middleman::Util.instrument 'sprockets', name: 'manipulator.linked_resources' do
          @linked_assets.map do |path|
            asset = environment[path]
            generate_resource(sprockets_asset_path(asset), asset.filename, asset.logical_path)
          end
        end

        ::Middleman::Util.instrument 'sprockets', name: 'manipulator.ignore_resources' do
          all_resources = base_resources + sprockets_resources + linked_resources

          if app.extensions[:sitemap_ignore].respond_to?(:manipulate_resource_list)
            app.extensions[:sitemap_ignore].manipulate_resource_list all_resources
          else
            all_resources
          end
        end
      end

      Contract ::Middleman::Sitemap::Resource => Bool
      def processible? r
        !r.is_a?(Resource) && !r.file_descriptor.nil? && interface.processible?(r.source_file)
      end

      Contract String => Bool
      def check_asset path
        if environment[path]
          @linked_assets << path
          true
        else
          false
        end
      end

      Contract ::Sprockets::Asset => String
      def sprockets_asset_path sprockets_asset
        File.join(options[:imported_asset_path], sprockets_asset.logical_path)
      end

      private

        def expose_app_helpers_to_sprockets!
          @environment.context_class.class_eval do
            def current_resource
              logger.error "The use of `current_resource` in sprockets assets isn't currently implemented"
              nil
            end

            def mm_context
              @_mm_context ||= app.template_context_class.new(app)
            end

            def method_missing method, *args, &block
              if mm_context.respond_to?(method)
                return mm_context.send method, *args, &block
              end

              super
            end

            def respond_to? method, include_private=false
              super || mm_context.respond_to?(method, include_private)
            end
          end
        end

        Contract ::Middleman::Sitemap::Resource => Or[::Middleman::Sitemap::Resource, Resource]
        def process_sprockets_resource resource
          ::Middleman::Util.instrument 'sprockets', name: 'process_resource', resource: resource do
            sprockets_resource = generate_resource(resource.path, resource.source_file, resource.path)

            if sprockets_resource.respond_to?(:sprockets_asset) && !sprockets_resource.errored?
              @linked_assets.merge sprockets_resource.sprockets_asset.links
            end

            sprockets_resource
          end
        rescue => e
          logger.error("== Sprockets Debug: #{resource}")
          logger.error("== Sprockets Debug: #{sprockets_resource}") if defined?(sprockets_resource)
          raise e<commit_msg>refactor: start storing the sprockets resources<commit_after>require 'sprockets'
require 'middleman-core/contracts'
require 'middleman-core/sitemap/resource'

require_relative 'resource'
require_relative 'interface'

module Middleman
  module Sprockets
    class Extension < Extension
      attr_reader :environment,
                  :interface

      expose_to_config   sprockets: :environment
      expose_to_template sprockets: :environment

      option :supported_output_extensions, ['.css', '.js'], 'Output extensions sprockets should process'
      option :imported_asset_path,         'assets',        'Where under source imported assets should be placed.'
      option :expose_middleman_helpers,    false,           'Whether to expose middleman helpers to sprockets.'

      Contract ::Middleman::Application, Hash, Maybe[Proc] => Any
      def initialize app, options_hash={}, &block
        super

        @linked_assets       = Set.new
        @sprockets_resources = Set.new
        @environment         = ::Sprockets::Environment.new
        @interface           = Interface.new options, @environment

        use_sassc_if_available
      end

      Contract Any
      def after_configuration
        @environment.append_path((app.source_dir + app.config[:js_dir]).to_s)
        @environment.append_path((app.source_dir + app.config[:css_dir]).to_s)
        @environment.append_path(app.source_dir.to_s)

        append_paths_from_gems

        the_app = app
        the_env = environment

        @environment.context_class.send(:define_method, :app)  { the_app }
        @environment.context_class.send(:define_method, :data) { the_app.data }
        @environment.context_class.send(:define_method, :env)  { the_env }

        @environment.context_class.class_eval do
          def asset_path path, options={}
            # Handle people calling with the Middleman/Padrino asset path signature
            if path.is_a?(::Symbol) && !options.is_a?(::Hash)
              kind = path
              path = options
            else
              kind = {
                image: :images,
                font: :fonts,
                javascript: :js,
                stylesheet: :css
              }.fetch(options[:type], options[:type])
            end

            if File.extname(path).empty?
              path << { js: '.js', css: '.css' }.fetch(kind, '')
            end

            if app.extensions[:sprockets].check_asset(path)
              app.extensions[:sprockets].sprockets_asset_path(env[path]).sub(/^\/?/, '/')
            else
              app.asset_path(kind, path)
            end
          end
        end

        expose_app_helpers_to_sprockets! if options[:expose_middleman_helpers]
      end

      Contract ResourceList => ResourceList
      def manipulate_resource_list resources
        sprockets_resources, base_resources = resources.partition(&method(:processible?))
        ::Middleman::Util.instrument 'sprockets', name: 'manipulator.sprockets_resources' do
          sprockets_resources.map!(&method(:process_sprockets_resource))
        end

        linked_resources = ::Middleman::Util.instrument 'sprockets', name: 'manipulator.linked_resources' do
          @linked_assets.map do |path|
            asset = environment[path]
            generate_resource(sprockets_asset_path(asset), asset.filename, asset.logical_path)
          end
        end

        ::Middleman::Util.instrument 'sprockets', name: 'manipulator.ignore_resources' do
          all_resources = base_resources + sprockets_resources + linked_resources

          if app.extensions[:sitemap_ignore].respond_to?(:manipulate_resource_list)
            app.extensions[:sitemap_ignore].manipulate_resource_list all_resources
          else
            all_resources
          end
        end
      end

      Contract ::Middleman::Sitemap::Resource => Bool
      def processible? r
        !r.is_a?(Resource) && !r.file_descriptor.nil? && interface.processible?(r.source_file)
      end

      Contract String => Bool
      def check_asset path
        if environment[path]
          @linked_assets << path
          true
        else
          false
        end
      end

      Contract ::Sprockets::Asset => String
      def sprockets_asset_path sprockets_asset
        File.join(options[:imported_asset_path], sprockets_asset.logical_path)
      end

      private

        def expose_app_helpers_to_sprockets!
          @environment.context_class.class_eval do
            def current_resource
              logger.error "The use of `current_resource` in sprockets assets isn't currently implemented"
              nil
            end

            def mm_context
              @_mm_context ||= app.template_context_class.new(app)
            end

            def method_missing method, *args, &block
              if mm_context.respond_to?(method)
                return mm_context.send method, *args, &block
              end

              super
            end

            def respond_to? method, include_private=false
              super || mm_context.respond_to?(method, include_private)
            end
          end
        end

        Contract ::Middleman::Sitemap::Resource => Or[::Middleman::Sitemap::Resource, Resource]
        def process_sprockets_resource resource
          ::Middleman::Util.instrument 'sprockets', name: 'process_resource', resource: resource do
            sprockets_resource = generate_resource(resource.path, resource.source_file, resource.path)
            @sprockets_resources << sprockets_resource
            unless sprockets_resource.errored?
              @linked_assets.merge sprockets_resource.sprockets_asset.links
            end

            sprockets_resource
          end
        rescue => e
          logger.error("== Sprockets Debug: #{resource}")
          logger.error("== Sprockets Debug: #{sprockets_resource}") if defined?(sprockets_resource)
          raise e
{'fraction_non_alphanumeric': 0.08777137042062415, 'fraction_numerical': 0.0, 'mean_word_length': 2.285873502368348, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2539313', 'n_tokens_mistral': 3283, 'n_tokens_neox': 3212, 'n_words': 669}