<commit_before>require 'uri'
require 'nokogiri'
require 'css_parser'

module MailStyle
  module InlineStyles
    DOCTYPE = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
    
    module InstanceMethods
      def create_mail_with_inline_styles
        write_inline_styles if @css.present?
        create_mail_without_inline_styles
      end
      
      protected
      
      def write_inline_styles
        # Parse only text/html parts
        @parts.select{|p| p.content_type == 'text/html'}.each do |part|
          part.body = parse_html(part.body)
        end
        
        # Parse single part emails if the body is html
        real_content_type, ctype_attrs = parse_content_type
        self.body = parse_html(body) if body.is_a?(String) && real_content_type == 'text/html'
      end

      def parse_html(html)
        # Parse original html
        html_document = create_html_document(html)
        html_document = absolutize_image_sources(html_document)

        # Write inline styles
        element_styles = {}
        
        css_parser.each_selector do |selector, declaration, specificity|
          html_document.css(selector).each do |element|
            declaration.to_s.split(';').each do |style|<commit_msg>Support for nested parts. This is neccessary for a multipart email with attachments.<commit_after>require 'uri'
require 'nokogiri'
require 'css_parser'

module MailStyle
  module InlineStyles
    DOCTYPE = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
    
    module InstanceMethods
      def create_mail_with_inline_styles
        write_inline_styles if @css.present?
        create_mail_without_inline_styles
      end
      
      protected
      
      def write_inline_styles
        # Parse only text/html parts
        parsable_parts(@parts).each do |part|
          part.body = parse_html(part.body)
        end
        
        # Parse single part emails if the body is html
        real_content_type, ctype_attrs = parse_content_type
        self.body = parse_html(body) if body.is_a?(String) && real_content_type == 'text/html'
      end
      
      def parsable_parts(parts)
        selected = []
        parts.each do |p|
          selected << p if p.content_type == 'text/html'
          selected += parsable_parts(p.parts)
        end
        selected
      end

      def parse_html(html)
        # Parse original html
        html_document = create_html_document(html)
        html_document = absolutize_image_sources(html_document)

        # Write inline styles
        element_styles = {}
        
        css_parser.each_selector do |selector, declaration, specificity|
          html_document.css(selector).each do |element|
            declaration.to_s.split(';').each do |style|
{'fraction_non_alphanumeric': 0.08442906574394464, 'fraction_numerical': 0.004152249134948097, 'mean_word_length': 2.462275449101796, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3722145', 'n_tokens_mistral': 867, 'n_tokens_neox': 840, 'n_words': 197}