<commit_before>require 'addressable/uri'
require 'sanitize'

class Govspeak::HtmlSanitizer
  class ImageSourceWhitelister
    def initialize(allowed_image_hosts)
      @allowed_image_hosts = allowed_image_hosts
    end

    def call(sanitize_context)
      return unless sanitize_context[:node_name] == "img"

      node = sanitize_context[:node]
      image_uri = Addressable::URI.parse(node['src'])
      unless image_uri.relative? || @allowed_image_hosts.include?(image_uri.host)
        node.unlink # the node isn't sanitary. Remove it from the document.
      end
    end
  end

  class TableCellTextAlignWhitelister
    def call(sanitize_context)
      return unless %w[td th].include?(sanitize_context[:node_name])

      node = sanitize_context[:node]

      # Kramdown uses text-align to allow table cells to be aligned
      # http://kramdown.gettalong.org/quickref.html#tables
      if invalid_style_attribute?(node['style'])
        node.remove_attribute('style')
      end
    end

    def invalid_style_attribute?(style)
      style && !style.match(/^text-align:\s*(center|left|right)$/)
    end
  end

  def initialize(dirty_html, options = {})
    @dirty_html = dirty_html
    @allowed_image_hosts = options[:allowed_image_hosts]
  end

  def sanitize
    transformers = [TableCellTextAlignWhitelister.new]
    if @allowed_image_hosts && @allowed_image_hosts.any?
      transformers << ImageSourceWhitelister.new(@allowed_image_hosts)
    end
    Sanitize.clean(@dirty_html, Sanitize::Config.merge(sanitize_config, transformers: transformers))
  end

  def button_sanitize_config
    [
      "data-module",
      "data-tracking-code",
      "data-tracking-name"
    ]
  end

  def sanitize_config
    Sanitize::Config.merge(
      Sanitize::Config::RELAXED,
      elements: Sanitize::Config::RELAXED[:elements] + %w[govspeak-embed-attachment govspeak-embed-attachment-link],
      attributes: {
        :all => Sanitize::Config::RELAXED[:attributes][:all] + ["role", "aria-label"],
        "a"  => Sanitize::Config::RELAXED[:attributes]["a"] + button_sanitize_config,
        "th"  => Sanitize::Config::RELAXED[:attributes]["th"] + %w[style],
        "td"  => Sanitize::Config::RELAXED[:attributes]["td"] + %w[style],
        "govspeak-embed-attachment" => %w[content-id],
      }
    )
  end
end<commit_msg>Fix Style/WordArray offenses<commit_after>require 'addressable/uri'
require 'sanitize'

class Govspeak::HtmlSanitizer
  class ImageSourceWhitelister
    def initialize(allowed_image_hosts)
      @allowed_image_hosts = allowed_image_hosts
    end

    def call(sanitize_context)
      return unless sanitize_context[:node_name] == "img"

      node = sanitize_context[:node]
      image_uri = Addressable::URI.parse(node['src'])
      unless image_uri.relative? || @allowed_image_hosts.include?(image_uri.host)
        node.unlink # the node isn't sanitary. Remove it from the document.
      end
    end
  end

  class TableCellTextAlignWhitelister
    def call(sanitize_context)
      return unless %w[td th].include?(sanitize_context[:node_name])

      node = sanitize_context[:node]

      # Kramdown uses text-align to allow table cells to be aligned
      # http://kramdown.gettalong.org/quickref.html#tables
      if invalid_style_attribute?(node['style'])
        node.remove_attribute('style')
      end
    end

    def invalid_style_attribute?(style)
      style && !style.match(/^text-align:\s*(center|left|right)$/)
    end
  end

  def initialize(dirty_html, options = {})
    @dirty_html = dirty_html
    @allowed_image_hosts = options[:allowed_image_hosts]
  end

  def sanitize
    transformers = [TableCellTextAlignWhitelister.new]
    if @allowed_image_hosts && @allowed_image_hosts.any?
      transformers << ImageSourceWhitelister.new(@allowed_image_hosts)
    end
    Sanitize.clean(@dirty_html, Sanitize::Config.merge(sanitize_config, transformers: transformers))
  end

  def button_sanitize_config
    %w[
      data-module
      data-tracking-code
      data-tracking-name
    ]
  end

  def sanitize_config
    Sanitize::Config.merge(
      Sanitize::Config::RELAXED,
      elements: Sanitize::Config::RELAXED[:elements] + %w[govspeak-embed-attachment govspeak-embed-attachment-link],
      attributes: {
        :all => Sanitize::Config::RELAXED[:attributes][:all] + %w[role aria-label],
        "a"  => Sanitize::Config::RELAXED[:attributes]["a"] + button_sanitize_config,
        "th"  => Sanitize::Config::RELAXED[:attributes]["th"] + %w[style],
        "td"  => Sanitize::Config::RELAXED[:attributes]["td"] + %w[style],
        "govspeak-embed-attachment" => %w[content-id],
      }
    )
  end
end
{'fraction_non_alphanumeric': 0.12247529007305544, 'fraction_numerical': 0.0, 'mean_word_length': 3.7210953346855984, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 13, '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': '2110717', 'n_tokens_mistral': 1511, 'n_tokens_neox': 1505, 'n_words': 254}