<commit_before>module Footnotes
  class Filter
    @@no_style = false
    @@multiple_notes = false
    @@klasses = []

    # Default link prefix is textmate
    @@prefix = 'txmt://open?url=file://%s&amp;line=%d&amp;column=%d'

    # Edit notes
    @@notes = [ :controller, :view, :layout, :partials, :stylesheets, :javascripts ]
    # Show notes
    @@notes += [ :assigns, :session, :cookies, :params, :filters, :routes, :env, :queries, :log, :general ]

    # Change queries for rpm note when available
    # if defined?(NewRelic)
    #  @@notes.delete(:queries)
    #  @@notes << :rpm
    # end

    # :no_style       => If you don't want the style to be appended to your pages
    # :notes          => Class variable that holds the notes to be processed
    # :prefix         => Prefix appended to FootnotesLinks
    # :multiple_notes => Set to true if you want to open several notes at the same time
    cattr_accessor :no_style, :notes, :prefix, :multiple_notes

    class << self
      # Method called to start the notes
      # It's a before filter prepend in the controller
      #
      def before(controller)
        Footnotes::Filter.start!(controller)
      end

      # Method that calls Footnotes to attach its contents
      #
      def after(controller)
        filter = Footnotes::Filter.new(controller)
        filter.add_footnotes!
        filter.close!(controller)
      end

      # Calls the class method start! in each note
      # Sometimes notes need to set variables or clean the environment to work properly
      # This method allows this kind of setup
      #
      def start!(controller)
        @@klasses = []

        each_with_rescue(@@notes.flatten) do |note|
          klass = "Footnotes::Notes::#{note.to_s.camelize}Note".constantize
          klass.start!(controller) if klass.respond_to?(:start!)
          @@klasses << klass
        end
      end

      # Process notes, discarding only the note if any problem occurs
      #
      def each_with_rescue(notes)
        delete_me = []

        notes.each do |note|
          begin
            yield note
          rescue Exception => e
            # Discard note if it has a problem
            log_error("Footnotes #{note.to_s.camelize}Note Exception", e)
            delete_me << note
            next
          end
        end

        delete_me.each{ |note| notes.delete(note) }
        return notes
      end

      # Logs the error using specified title and format
      #
      def log_error(title, exception)
        RAILS_DEFAULT_LOGGER.error "#{title}: #{exception}\n#{exception.backtrace.join("\n")}"
      end

      # If none argument is sent, simply return the prefix.
      # Otherwise, replace the args in the prefix.
      #
      def prefix(*args)
        if args.empty?
          @@prefix
        else
          format(@@prefix, *args)
        end
      end

    end

    def initialize(controller)
      @controller = controller
      @template = controller.instance_variable_get(:@template)
      @body = controller.response.body
      @notes = []
    end

    def add_footnotes!
      add_footnotes_without_validation! if valid?
    rescue Exception => e
      # Discard footnotes if there are any problems
      self.class.log_error("Footnotes Exception", e)
    end

    # Calls the class method close! in each note
    # Sometimes notes need to finish their work even after being read
    # This method allows this kind of work
    #
    def close!(controller)
      each_with_rescue(@@klasses) do |klass|
        klass.close!(controller)
      end
    end

    protected
      def valid?
        performed_render? && valid_format? && valid_content_type? && @body.is_a?(String) && !component_request? && !xhr?
      end

      def add_footnotes_without_validation!
        initialize_notes!
        insert_styles unless @@no_style
        insert_footnotes
      end

      def initialize_notes!
        each_with_rescue(@@klasses) do |klass|
          note = klass.new(@controller)
          @notes << note if note.respond_to?(:valid?) && note.valid?
        end
      end

      def performed_render?
        @controller.instance_variable_get(:@performed_render)
      end

      def valid_format?
        [:html,:rhtml,:xhtml,:rxhtml].include?(@template.template_format.to_sym)
      end

      def valid_content_type?
        c = @controller.response.headers['Content-Type'].to_s
        (c.empty? || c =~ /html/)
      end

      def component_request?
        @controller.instance_variable_get(:@parent_controller)
      end

      def xhr?
        @controller.request.xhr?
      end

      #
      # Insertion methods
      #

      def insert_styles
        insert_text :before, /<\/head>/i, <<-HTML
        <!-- Footnotes Style -->
        <style type="text/css"><commit_msg>Allow footnotes to be disabled with a parameter<commit_after>module Footnotes
  class Filter
    @@no_style = false
    @@multiple_notes = false
    @@klasses = []

    # Default link prefix is textmate
    @@prefix = 'txmt://open?url=file://%s&amp;line=%d&amp;column=%d'

    # Edit notes
    @@notes = [ :controller, :view, :layout, :partials, :stylesheets, :javascripts ]
    # Show notes
    @@notes += [ :assigns, :session, :cookies, :params, :filters, :routes, :env, :queries, :log, :general ]

    # Change queries for rpm note when available
    # if defined?(NewRelic)
    #  @@notes.delete(:queries)
    #  @@notes << :rpm
    # end

    # :no_style       => If you don't want the style to be appended to your pages
    # :notes          => Class variable that holds the notes to be processed
    # :prefix         => Prefix appended to FootnotesLinks
    # :multiple_notes => Set to true if you want to open several notes at the same time
    cattr_accessor :no_style, :notes, :prefix, :multiple_notes

    class << self
      # Method called to start the notes
      # It's a before filter prepend in the controller
      #
      def before(controller)
        Footnotes::Filter.start!(controller)
      end

      # Method that calls Footnotes to attach its contents
      #
      def after(controller)
        filter = Footnotes::Filter.new(controller)
        filter.add_footnotes!
        filter.close!(controller)
      end

      # Calls the class method start! in each note
      # Sometimes notes need to set variables or clean the environment to work properly
      # This method allows this kind of setup
      #
      def start!(controller)
        @@klasses = []

        each_with_rescue(@@notes.flatten) do |note|
          klass = "Footnotes::Notes::#{note.to_s.camelize}Note".constantize
          klass.start!(controller) if klass.respond_to?(:start!)
          @@klasses << klass
        end
      end

      # Process notes, discarding only the note if any problem occurs
      #
      def each_with_rescue(notes)
        delete_me = []

        notes.each do |note|
          begin
            yield note
          rescue Exception => e
            # Discard note if it has a problem
            log_error("Footnotes #{note.to_s.camelize}Note Exception", e)
            delete_me << note
            next
          end
        end

        delete_me.each{ |note| notes.delete(note) }
        return notes
      end

      # Logs the error using specified title and format
      #
      def log_error(title, exception)
        RAILS_DEFAULT_LOGGER.error "#{title}: #{exception}\n#{exception.backtrace.join("\n")}"
      end

      # If none argument is sent, simply return the prefix.
      # Otherwise, replace the args in the prefix.
      #
      def prefix(*args)
        if args.empty?
          @@prefix
        else
          format(@@prefix, *args)
        end
      end

    end

    def initialize(controller)
      @controller = controller
      @template = controller.instance_variable_get(:@template)
      @body = controller.response.body
      @notes = []
    end

    def add_footnotes!
      add_footnotes_without_validation! if valid?
    rescue Exception => e
      # Discard footnotes if there are any problems
      self.class.log_error("Footnotes Exception", e)
    end

    # Calls the class method close! in each note
    # Sometimes notes need to finish their work even after being read
    # This method allows this kind of work
    #
    def close!(controller)
      each_with_rescue(@@klasses) do |klass|
        klass.close!(controller)
      end
    end

    protected
      def valid?
        performed_render? && valid_format? && valid_content_type? &&
          @body.is_a?(String) && !component_request? && !xhr? &&
          !footnotes_disabled?
      end

      def add_footnotes_without_validation!
        initialize_notes!
        insert_styles unless @@no_style
        insert_footnotes
      end

      def initialize_notes!
        each_with_rescue(@@klasses) do |klass|
          note = klass.new(@controller)
          @notes << note if note.respond_to?(:valid?) && note.valid?
        end
      end

      def performed_render?
        @controller.instance_variable_get(:@performed_render)
      end

      def valid_format?
        [:html,:rhtml,:xhtml,:rxhtml].include?(@template.template_format.to_sym)
      end

      def valid_content_type?
        c = @controller.response.headers['Content-Type'].to_s
        (c.empty? || c =~ /html/)
      end

      def component_request?
        @controller.instance_variable_get(:@parent_controller)
      end

      def xhr?
        @controller.request.xhr?
      end

      def footnotes_disabled?
        @controller.params[:footnotes] == "false"
      end

      #
      # Insertion methods
      #

      def insert_styles
        insert_text :before, /<\/head>/i, <<-HTML
        <!-- Footnotes Style -->
        <style type="text/css">
{'fraction_non_alphanumeric': 0.09714110052259453, 'fraction_numerical': 0.0, 'mean_word_length': 2.229649238914626, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 21, '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': '6591040', 'n_tokens_mistral': 2815, 'n_tokens_neox': 2749, 'n_words': 800}