emoji_filter.rb 3.5 KB
Newer Older
1 2
module Banzai
  module Filter
H
henrik 已提交
3
    # HTML filter that replaces :emoji: and unicode with images.
4 5 6 7 8 9 10 11 12 13
    #
    # Based on HTML::Pipeline::EmojiFilter
    #
    # Context options:
    #   :asset_root
    #   :asset_host
    class EmojiFilter < HTML::Pipeline::Filter
      IGNORED_ANCESTOR_TAGS = %w(pre code tt).to_set

      def call
14
        search_text_nodes(doc).each do |node|
15 16
          content = node.to_html
          next if has_ancestor?(node, IGNORED_ANCESTOR_TAGS)
H
henrik 已提交
17 18 19 20 21 22
          if content.include?(':') || node.text.match(emoji_unicode_pattern)
            html = emoji_name_image_filter(content)
            html = emoji_unicode_image_filter(html)
            next if html == content
            node.replace(html)
          end
23 24 25 26 27 28 29 30 31 32 33

        end

        doc
      end

      # Replace :emoji: with corresponding images.
      #
      # text - String text to replace :emoji: in.
      #
      # Returns a String with :emoji: replaced with images.
H
henrik 已提交
34
      def emoji_name_image_filter(text)
35 36 37 38 39 40
        text.gsub(emoji_pattern) do |match|
          name = $1
          "<img class='emoji' title=':#{name}:' alt=':#{name}:' src='#{emoji_url(name)}' height='20' width='20' align='absmiddle' />"
        end
      end

H
henrik 已提交
41 42 43 44 45 46 47 48 49 50 51 52

      # Replace unicode emojis with corresponding images if they exist.
      #
      # text - String text to replace unicode emojis in.
      #
      # Returns a String with unicode emojis replaced with images.

      def emoji_unicode_image_filter(text)
        text.gsub(emoji_unicode_pattern) do |moji|
          "<img class='emoji' title=':#{Gitlab::Emoji.emojis_by_moji[moji]['name']}:' alt=':#{Gitlab::Emoji.emojis_by_moji[moji]['name']}:' src='#{emoji_unicode_url(moji)}' height='20' width='20' align='absmiddle' />"
        end
      end
53 54 55 56
      # Build a regexp that matches all valid :emoji: names.
      def self.emoji_pattern
        @emoji_pattern ||= /:(#{Gitlab::Emoji.emojis_names.map { |name| Regexp.escape(name) }.join('|')}):/
      end
H
henrik 已提交
57 58 59
      # Build a regexp that matches all valid unicode emojis names.
      def self.emoji_unicode_pattern
        @emoji_unicode_pattern ||= /(#{Gitlab::Emoji.emojis_unicodes.map { |moji| Regexp.escape(moji) }.join('|')})/
60

H
henrik 已提交
61
      end
62 63 64
      private

      def emoji_url(name)
R
Robert Speicher 已提交
65 66
        emoji_path = emoji_filename(name)

67 68 69 70 71 72 73 74 75 76 77 78
        if context[:asset_host]
          # Asset host is specified.
          url_to_image(emoji_path)
        elsif context[:asset_root]
          # Gitlab url is specified
          File.join(context[:asset_root], url_to_image(emoji_path))
        else
          # All other cases
          url_to_image(emoji_path)
        end
      end

H
henrik 已提交
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
      def emoji_unicode_url(moji)
        emoji_unicode_path = emoji_unicode_filename(moji)

        if context[:asset_host]
          # Asset host is specified.
          url_to_image(emoji_unicode_path)
        elsif context[:asset_root]
          # Gitlab url is specified
          File.join(context[:asset_root], url_to_image(emoji_unicode_path))
        else
          # All other cases
          url_to_image(emoji_unicode_path)
        end
      end

94 95 96 97 98 99 100 101 102
      def url_to_image(image)
        ActionController::Base.helpers.url_to_image(image)
      end

      def emoji_pattern
        self.class.emoji_pattern
      end

      def emoji_filename(name)
103
        "#{Gitlab::Emoji.emoji_filename(name)}.png"
104
      end
H
henrik 已提交
105 106 107 108 109 110 111
      def emoji_unicode_pattern
        self.class.emoji_unicode_pattern
      end

      def emoji_unicode_filename(name)
        "#{Gitlab::Emoji.emoji_unicode_filename(name)}.png"
      end
112 113 114
    end
  end
end