<commit_before>module Rubaidh
  module Validations
    module RegularExpressions
      module RegexStr
        Hostname = '[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]'.freeze
        FullyQualifiedDomainName = "#{Hostname}(\\.#{Hostname})+\\.?".freeze

        EmailAddressLocalPartSpecialCharacters = Regexp.escape('!#$%&\'*+-/=?^_`{|}~').freeze
        EmailAddressLocalPartUnquoted = "[[:alnum:]#{EmailAddressLocalPartSpecialCharacters}][[:alnum:]#{EmailAddressLocalPartSpecialCharacters}\.]*".freeze
        EmailAddressLocalPartQuoted = '[\x00-\xFF]+'.freeze
        EmailAddressLocalPart = "(#{EmailAddressLocalPartUnquoted}|\"#{EmailAddressLocalPartQuoted}\")".freeze
        EmailAddress = "#{EmailAddressLocalPart}@#{FullyQualifiedDomainName}".freeze
      end

      Hostname = /\A#{RegexStr::Hostname}\Z/.freeze
      FullyQualifiedDomainName = /\A#{RegexStr::FullyQualifiedDomainName}\Z/.freeze
      EmailAddress = /\A#{RegexStr::EmailAddress}\Z/.freeze
    end

    def self.included(base)
      base.extend ClassMethods
    end

    module ClassMethods
      def validates_hostname_format_of(*attr_names)
        options = attr_names.extract_options!

        configuration = { :with => Rubaidh::Validations::RegularExpressions::Hostname }
        configuration.update(options)
        validates_format_of *(attr_names + [configuration])
      end

      def validates_fully_qualified_domain_name_format_of(*attr_names)
        options = attr_names.extract_options!

        format_configuration = { :with => Rubaidh::Validations::RegularExpressions::FullyQualifiedDomainName }
        format_configuration.update(options)
        validates_format_of *(attr_names + [format_configuration])

        length_configuration = { :within => 5..255 }
        length_configuration.update(options)
        validates_length_of *(attr_names + [length_configuration])
      end

      def validates_email_address_format_of(*attr_names)
        options = attr_names.extract_options!
        configuration = { :with => Rubaidh::Validations::RegularExpressions::EmailAddress }
        configuration.update(options)
        validates_format_of *(attr_names + [configuration])
      end
    end
  end
end<commit_msg>Add in the start of a strict validation for URLs.<commit_after>module Rubaidh
  module Validations
    module RegularExpressions
      module RegexStr
        Hostname = '[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]'.freeze
        FullyQualifiedDomainName = "#{Hostname}(\\.#{Hostname})+\\.?".freeze

        EmailAddressLocalPartSpecialCharacters = Regexp.escape('!#$%&\'*+-/=?^_`{|}~').freeze
        EmailAddressLocalPartUnquoted = "[[:alnum:]#{EmailAddressLocalPartSpecialCharacters}][[:alnum:]#{EmailAddressLocalPartSpecialCharacters}\.]*".freeze
        EmailAddressLocalPartQuoted = '[\x00-\xFF]+'.freeze
        EmailAddressLocalPart = "(#{EmailAddressLocalPartUnquoted}|\"#{EmailAddressLocalPartQuoted}\")".freeze
        EmailAddress = "#{EmailAddressLocalPart}@#{FullyQualifiedDomainName}".freeze

        Protocol = "https?".freeze
        OptionalPort = "(:[0-9]{1,5})?".freeze
        OptionalPath = "([[:alnum:]._~/-]|%[0-9a-fA-F]+)*"
      end

      Hostname = /\A#{RegexStr::Hostname}\Z/.freeze
      FullyQualifiedDomainName = /\A#{RegexStr::FullyQualifiedDomainName}\Z/.freeze
      EmailAddress = /\A#{RegexStr::EmailAddress}\Z/.freeze

      # FIXME: We should be checking for query strings and fragments here, but
      # pragmatism has won out today.
      Url = /\A#{RegexStr::Protocol}:\/\/#{RegexStr::FullyQualifiedDomainName}#{RegexStr::OptionalPort}#{RegexStr::OptionalPath}/.freeze
    end

    def self.included(base)
      base.extend ClassMethods
    end

    module ClassMethods
      def validates_hostname_format_of(*attr_names)
        options = attr_names.extract_options!

        configuration = { :with => Rubaidh::Validations::RegularExpressions::Hostname }
        configuration.update(options)
        validates_format_of *(attr_names + [configuration])
      end

      def validates_fully_qualified_domain_name_format_of(*attr_names)
        options = attr_names.extract_options!

        format_configuration = { :with => Rubaidh::Validations::RegularExpressions::FullyQualifiedDomainName }
        format_configuration.update(options)
        validates_format_of *(attr_names + [format_configuration])

        length_configuration = { :within => 5..255 }
        length_configuration.update(options)
        validates_length_of *(attr_names + [length_configuration])
      end

      def validates_email_address_format_of(*attr_names)
        options = attr_names.extract_options!
        configuration = { :with => Rubaidh::Validations::RegularExpressions::EmailAddress }
        configuration.update(options)
        validates_format_of *(attr_names + [configuration])
      end

      def validates_url_format_of(*attr_names)
        options = attr_names.extract_options!
        configuration = { :with => Rubaidh::Validations::RegularExpressions::Url }
        configuration.update(options)
        validates_format_of *(attr_names + [configuration])
      end
    end
  end
end
{'fraction_non_alphanumeric': 0.12568093385214008, 'fraction_numerical': 0.007003891050583658, 'mean_word_length': 3.720844811753903, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 12, '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': '1431506', 'n_tokens_mistral': 1563, 'n_tokens_neox': 1515, 'n_words': 211}