From dfde59f631ba200b95aa01691d67939521ccaa3e Mon Sep 17 00:00:00 2001 From: Joffrey JAFFEUX Date: Wed, 26 Jun 2019 15:11:04 +0200 Subject: [PATCH] FIX: provides an emoji helper to replace codes by images (#7802) --- app/helpers/emoji_helper.rb | 19 ++++++++ app/models/emoji.rb | 19 +++++--- .../exceptions/_not_found_topics.html.erb | 2 +- spec/helpers/emoji_helper_spec.rb | 24 ++++++++++ spec/models/emoji_spec.rb | 48 +++++++++++++++++++ 5 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 app/helpers/emoji_helper.rb create mode 100644 spec/helpers/emoji_helper_spec.rb diff --git a/app/helpers/emoji_helper.rb b/app/helpers/emoji_helper.rb new file mode 100644 index 00000000000..f1f13b1e579 --- /dev/null +++ b/app/helpers/emoji_helper.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module EmojiHelper + def emoji_codes_to_img(str) + return if str.blank? + + str = str.gsub(/:([\w\-+]*(?::t\d)?):/) do |name| + code = $1 + + if Emoji.exists?(code) + "\"#{code}\"" + else + name + end + end + + raw(str) + end +end diff --git a/app/models/emoji.rb b/app/models/emoji.rb index e6aa723da99..22076c03851 100644 --- a/app/models/emoji.rb +++ b/app/models/emoji.rb @@ -8,12 +8,7 @@ class Emoji include ActiveModel::SerializerSupport - attr_reader :path - attr_accessor :name, :url - - def initialize(path = nil) - @path = path - end + attr_accessor :name, :url, :tonable def self.all Discourse.cache.fetch(cache_key("all_emojis")) { standard | custom } @@ -48,19 +43,29 @@ class Emoji end def self.[](name) - Emoji.custom.detect { |e| e.name == name } + name = name.delete_prefix(':').delete_suffix(':') + is_toned = name.match?(/.+:t[1-6]/) + normalized_name = name.gsub(/(.+):t[1-6]/, '\1') + + Emoji.all.detect do |e| + e.name == normalized_name && + (!is_toned || (is_toned && e.tonable)) + end end def self.create_from_db_item(emoji) name = emoji["name"] filename = emoji['filename'] || name + Emoji.new.tap do |e| e.name = name + e.tonable = Emoji.tonable_emojis.include?(name) e.url = Emoji.url_for(filename) end end def self.url_for(name) + name = name.delete_prefix(':').delete_suffix(':').gsub(/(.+):t([1-6])/, '\1/\2') "#{Discourse.base_uri}/images/emoji/#{SiteSetting.emoji_set}/#{name}.png?v=#{EMOJI_VERSION}" end diff --git a/app/views/exceptions/_not_found_topics.html.erb b/app/views/exceptions/_not_found_topics.html.erb index 59cf088c33e..2e6c107e3c6 100644 --- a/app/views/exceptions/_not_found_topics.html.erb +++ b/app/views/exceptions/_not_found_topics.html.erb @@ -3,7 +3,7 @@ <% @top_viewed.each do |t| %>
- <%= link_to t.title, t.relative_url %><%= category_badge(t.category) %> + <%= link_to emoji_codes_to_img(t.fancy_title), t.relative_url %><%= category_badge(t.category) %>
<% end %> " class="btn btn-default"><%= t 'page_not_found.see_more' %>… diff --git a/spec/helpers/emoji_helper_spec.rb b/spec/helpers/emoji_helper_spec.rb new file mode 100644 index 00000000000..7d7fa32d6c5 --- /dev/null +++ b/spec/helpers/emoji_helper_spec.rb @@ -0,0 +1,24 @@ +# coding: utf-8 +# frozen_string_literal: true + +require 'rails_helper' + +describe EmojiHelper do + + describe "emoji_codes_to_img" do + it "replaces emoji codes by images" do + str = "This is a good day :woman: :man:t4:" + replaced_str = helper.emoji_codes_to_img(str) + + expect(replaced_str).to eq("This is a good day \"woman\" \"man:t4\"") + end + + it "doesn't replace if code doesn't exist" do + str = "This is a good day :woman: :foo: :bar:t4: :man:t8:" + replaced_str = helper.emoji_codes_to_img(str) + + expect(replaced_str).to eq("This is a good day \"woman\" :foo: :bar:t4: :man:t8:") + end + end + +end diff --git a/spec/models/emoji_spec.rb b/spec/models/emoji_spec.rb index 16283245c46..c36f3161f99 100644 --- a/spec/models/emoji_spec.rb +++ b/spec/models/emoji_spec.rb @@ -44,4 +44,52 @@ describe Emoji do end end + describe '.url_for' do + expected_url = "/images/emoji/twitter/blonde_woman.png?v=#{Emoji::EMOJI_VERSION}" + expected_toned_url = "/images/emoji/twitter/blonde_woman/6.png?v=#{Emoji::EMOJI_VERSION}" + + it 'should return url with filename' do + expect(Emoji.url_for("blonde_woman")).to eq(expected_url) + end + + it 'should return url with skin toned filename' do + expect(Emoji.url_for("blonde_woman/6")).to eq(expected_toned_url) + end + + it 'should return url with code' do + expect(Emoji.url_for(":blonde_woman:")).to eq(expected_url) + end + + it 'should return url with skin toned code' do + expect(Emoji.url_for(":blonde_woman:t6:")).to eq(expected_toned_url) + expect(Emoji.url_for("blonde_woman:t6")).to eq(expected_toned_url) + end + end + + describe '.exists?' do + it 'finds existing emoji' do + expect(Emoji.exists?(":blonde_woman:")).to be(true) + expect(Emoji.exists?("blonde_woman")).to be(true) + end + + it 'finds existing skin toned emoji' do + expect(Emoji.exists?(":blonde_woman:t1:")).to be(true) + expect(Emoji.exists?("blonde_woman:t6")).to be(true) + end + + it 'finds existing custom emoji' do + CustomEmoji.create!(name: 'test', upload_id: 9999) + Emoji.clear_cache + expect(Emoji.exists?(":test:")).to be(true) + expect(Emoji.exists?("test")).to be(true) + end + + it 'doesn’t find non-existing emoji' do + expect(Emoji.exists?(":foo-bar:")).to be(false) + expect(Emoji.exists?(":blonde_woman:t7:")).to be(false) + expect(Emoji.exists?("blonde_woman:t0")).to be(false) + expect(Emoji.exists?("blonde_woman:t")).to be(false) + end + end + end