# encoding: utf-8
require 'sanitize'

module HTML
  class Pipeline

    # HTML filter with sanization routines and whitelists. This module defines
    # what HTML is allowed in user provided content and fixes up issues with
    # unbalanced tags and whatnot.
    #
    # See the Sanitize docs for more information on the underlying library:
    #
    # https://github.com/rgrove/sanitize/#readme
    #
    # Context options:
    #   :whitelist - The sanitizer whitelist configuration to use. This can be one
    #                of the options constants defined in this class or a custom
    #                sanitize options hash.
    #
    # This filter does not write additional information to the context.
    class SanitizationFilter < Filter

      # The main sanitization whitelist. Only these elements and attributes are
      # allowed through by default.
      WHITELIST = {
        :elements => %w(a abbr b blockquote br cite code dd del dfn div dl dt em
                        h1 h2 h3 h4 h5 h6 hr i img ins kbd li mark meter ol p pre
                        q s samp small source span strong sub sup table tbody td
                        tfooter th thead tr time ul var video wbr),
        :remove_contents => ['script'],
        :attributes => {
          :all         => ['data-after', 'data-id', 'id', 'title', 'class'],
          'a'          => ['href', 'name'],
          'blockquote' => ['cite'],
          'img'        => ['alt', 'height', 'src', 'width'],
          'q'          => ['cite'],
          'source'     => ['src', 'type', 'media'],
          'time'       => ['datetime'],
          'video'      => ['src', 'controls']
        },
        :protocols => {
          'a'          => {'href' => ['ftp', 'http', 'https', 'irc', 'mailto', 'xmpp', 'ed2k', 'magnet', :relative]},
          'blockquote' => {'cite' => ['http', 'https', :relative]},
          'img'        => {'src'  => ['http', 'https', :relative]},
          'q'          => {'cite' => ['http', 'https', :relative]}
        }
      }

      # A more limited sanitization whitelist. This includes all attributes,
      # protocols, and transformers from WHITELIST but with a more locked down
      # set of allowed elements.
      LIMITED = WHITELIST.merge(
        :elements => %w(b i strong em a pre code img ins del sup sub p ol ul li))

      # Strip all HTML tags from the document.
      FULL = { :elements => [] }

      # Sanitize markup using the Sanitize library.
      def call
        Sanitize.node!(doc, whitelist)
      end

      # The whitelist to use when sanitizing. This can be passed in the context
      # hash to the filter but defaults to WHITELIST constant value above.
      def whitelist
        context[:whitelist] || WHITELIST
      end
    end

  end
end