<commit_before>module TableCloth
  module Presenters
    class Default < ::TableCloth::Presenter
      def render_table
        @render_table ||= ElementFactory::Element.new(:table, tag_options(:table)).tap do |table|
          table << thead
          table << tbody
        end
      end

      def thead
        @thead ||= ElementFactory::Element.new(:thead, tag_options(:thead)).tap do |thead|
          thead << thead_row
        end
      end

      def tbody
        @tbody ||= ElementFactory::Element.new(:tbody, tag_options(:tbody)).tap do |tbody|
          objects.each {|object| tbody << row_for_object(object) }
        end
      end

      private

      def thead_row
        @thead_row ||= ElementFactory::Element.new(:tr, tag_options(:tr)).tap do |row|
          column_names.each do |name|
            row << ElementFactory::Element.new(:th, tag_options(:th).merge(text: name))
          end
        end
      end

      def row_for_object(object)
        ElementFactory::Element.new(:tr, tag_options(:tr)).tap do |row|
          columns.each do |column|
            row << column_for_object(column, object)
          end
        end
      end

      def column_for_object(column, object)
        td_options = column.options[:td_options] || {}
        value = column.value(object, view_context, table)

        if value.is_a?(Array)
          options = value.pop
          value   = value.shift

          td_options.update(options)
        end

        td_options[:text] = value

        ElementFactory::Element.new(:td, tag_options(:td).merge(td_options))
      end
    end
  end
end<commit_msg>Check string safety in default presenter for column values.<commit_after>module TableCloth
  module Presenters
    class Default < ::TableCloth::Presenter
      def render_table
        @render_table ||= ElementFactory::Element.new(:table, tag_options(:table)).tap do |table|
          table << thead
          table << tbody
        end
      end

      def thead
        @thead ||= ElementFactory::Element.new(:thead, tag_options(:thead)).tap do |thead|
          thead << thead_row
        end
      end

      def tbody
        @tbody ||= ElementFactory::Element.new(:tbody, tag_options(:tbody)).tap do |tbody|
          objects.each {|object| tbody << row_for_object(object) }
        end
      end

      private

      def thead_row
        @thead_row ||= ElementFactory::Element.new(:tr, tag_options(:tr)).tap do |row|
          column_names.each do |name|
            row << ElementFactory::Element.new(:th, tag_options(:th).merge(text: name))
          end
        end
      end

      def row_for_object(object)
        ElementFactory::Element.new(:tr, tag_options(:tr)).tap do |row|
          columns.each do |column|
            row << column_for_object(column, object)
          end
        end
      end

      def column_for_object(column, object)
        td_options = column.options[:td_options] || {}
        value = column.value(object, view_context, table)

        if value.is_a?(Array)
          options = value.pop
          value   = value.shift

          td_options.update(options)
        end

        if value.html_safe?
          td_options[:inner_html] = value
        else
          td_options[:text] = value
        end

        ElementFactory::Element.new(:td, tag_options(:td).merge(td_options))
      end
    end
  end
end
{'fraction_non_alphanumeric': 0.10827647582319787, 'fraction_numerical': 0.0, 'mean_word_length': 2.157303370786517, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 3, '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': '1441582', 'n_tokens_mistral': 999, 'n_tokens_neox': 958, 'n_words': 217}