# frozen_string_literal: true

module Hanami
  class View
    # HTML-focused behavior for strings intended to be output in templates.
    #
    # @api public
    # @since 2.1.0
    module HTML
      # A string that has been marked as "HTML safe", ensuring that it is not automatically escaped
      # when used in HTML view templates.
      #
      # A SafeString is frozen when initialized to ensure it cannot be mutated after being marked as
      # safe, which could be an avenue for injection of unsafe content.
      #
      # @see String#html_safe
      #
      # @api public
      # @since 2.1.0
      class SafeString < String
        # @api public
        # @since 2.1.0
        def initialize(string)
          super(string)
          freeze
        end

        # @api private
        # @since 2.1.0
        private def initialize_copy(other)
          super
          freeze
        end

        # @return [true]
        #
        # @api public
        # @since 2.1.0
        def html_safe?
          true
        end

        # @return [self]
        #
        # @api public
        # @since 2.1.0
        def html_safe
          self
        end

        # @return [self]
        #
        # @api public
        # @since 2.1.0
        def to_s
          self
        end
      end

      # @api private
      # @since 2.1.0
      module StringExtensions
        # Returns the string as a {Hanami::View::HTML::SafeString}, ensuring the string is not
        # automatically escaped when used in HTML view templates.
        #
        # @return [Hanami::View::HTML::SafeString]
        #
        # @api public
        # @since 2.1.0
        def html_safe
          Hanami::View::HTML::SafeString.new(self)
        end
      end
    end
  end
end

class String
  # Prepend our `#html_safe` method so that it takes precedence over Active Support's. When both
  # methods are loaded, the more likely scenario is that the user will want Hanami's, since in the
  # context of a Hanami app, Active Support is more likely to be loaded incidentally, as a
  # transitive dependency of another gem.
  #
  # Having our `#html_safe` available via this module also means that a user can also choose to
  # _undefine_ this method within the module if they'd rather use Active Support's.
  prepend Hanami::View::HTML::StringExtensions
end

class Object
  # @return [false]
  #
  # @api public
  # @since 2.1.0
  def html_safe?
    false
  end
end

class Numeric
  # @return [true]
  #
  # @api public
  # @since 2.1.0
  def html_safe?
    true
  end
end


