Browse Source

Use the same emoji data on the frontend and backend (#4284)

* Use the same emoji data on the frontend and backend

* Move emoji.json to repository, add tests

This way you don't need to install node dependencies if you only
want to run Ruby code
Eugen Rochko 6 years ago
parent
commit
a390abdefb
5 changed files with 65 additions and 6 deletions
  1. 0 1
      Gemfile
  2. 10 5
      app/helpers/emoji_helper.rb
  3. 40 0
      app/lib/emoji.rb
  4. 0 0
      lib/assets/emoji.json
  5. 15 0
      spec/lib/emoji_spec.rb

+ 0 - 1
Gemfile

@@ -28,7 +28,6 @@ gem 'devise', '~> 4.2'
 gem 'devise-two-factor', '~> 3.0'
 gem 'doorkeeper', '~> 4.2'
 gem 'fast_blank', '~> 1.0'
-gem 'gemoji', '~> 3.0'
 gem 'goldfinger', '~> 1.2'
 gem 'hiredis', '~> 0.6'
 gem 'redis-namespace', '~> 1.5'

+ 10 - 5
app/helpers/emoji_helper.rb

@@ -1,19 +1,24 @@
 # frozen_string_literal: true
 
 module EmojiHelper
-  EMOJI_PATTERN = /(?<=[^[:alnum:]:]|\n|^):([\w+-]+):(?=[^[:alnum:]:]|$)/x
-
   def emojify(text)
     return text if text.blank?
 
-    text.gsub(EMOJI_PATTERN) do |match|
-      emoji = Emoji.find_by_alias($1) # rubocop:disable Rails/DynamicFindBy,Style/PerlBackrefs
+    text.gsub(emoji_pattern) do |match|
+      emoji = Emoji.instance.unicode($1) # rubocop:disable Style/PerlBackrefs
 
       if emoji
-        emoji.raw
+        emoji
       else
         match
       end
     end
   end
+
+  def emoji_pattern
+    @emoji_pattern ||=
+      /(?<=[^[:alnum:]:]|\n|^)
+      (#{Emoji.instance.names.map { |name| Regexp.escape(name) }.join('|')})
+      (?=[^[:alnum:]:]|$)/x
+  end
 end

+ 40 - 0
app/lib/emoji.rb

@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'singleton'
+
+class Emoji
+  include Singleton
+
+  def initialize
+    data = Oj.load(File.open(File.join(Rails.root, 'lib', 'assets', 'emoji.json')))
+
+    @map = {}
+
+    data.each do |_, emoji|
+      keys    = [emoji['shortname']] + emoji['aliases']
+      unicode = codepoint_to_unicode(emoji['unicode'])
+
+      keys.each do |key|
+        @map[key] = unicode
+      end
+    end
+  end
+
+  def unicode(shortcode)
+    @map[shortcode]
+  end
+
+  def names
+    @map.keys
+  end
+
+  private
+
+  def codepoint_to_unicode(codepoint)
+    if codepoint.include?('-')
+      codepoint.split('-').map(&:hex).pack('U')
+    else
+      [codepoint.hex].pack('U')
+    end
+  end
+end

File diff suppressed because it is too large
+ 0 - 0
lib/assets/emoji.json


+ 15 - 0
spec/lib/emoji_spec.rb

@@ -0,0 +1,15 @@
+require 'rails_helper'
+
+RSpec.describe Emoji do
+  describe '#unicode' do
+    it 'returns a unicode for a shortcode' do
+      expect(Emoji.instance.unicode(':joy:')).to eq '😂'
+    end
+  end
+
+  describe '#names' do
+    it 'returns an array' do
+      expect(Emoji.instance.names).to be_an Array
+    end
+  end
+end

Some files were not shown because too many files changed in this diff