Rails gem gemoji
Bài đăng này đã không được cập nhật trong 3 năm
Gem gemoji
Emoji là các biểu tượng và hình mặt cười được sử dụng trong các tin nhắn điện tử và các trang web. Gem gemoji hỗ trợ hiển thị emoji đối với các trang web được phát triển bằng RoR. Link tham khảo: https://github.com/github/gemoji.
a. Cài đặt:
- Thêm gem "gemoji" vào Gemfile.
gem "gemoji"
- Chạy bundle install để cài đặt gem "gemoji".
bundle install
b. Extract images để hiển thị image cho emoji:
- Để extract image hiển thị emoji trên web và lưu vào thư mục public/images/emoji , ta chạy câu lệnh
bundle exec gemoji extract public/images/emoji
- Đối với các máy chạy hệ điều hành window hoặc ubuntu, ta nhận được lỗi
Errno::ENOENT
- Theo source code của gem gemoji, nguyên nhân lỗi là do hệ điều hành ubuntu và window không có file
Apple Color Emoji.ttc
Emoji::Extractor
sử dụng biếnEMOJI_TTF
để lưu file ttc chứa toàn bộ hình ảnh emoji của hệ điều hành.
EMOJI_TTF = "/System/Library/Fonts/Apple Color Emoji.ttc"
- Ta có thể download file Apple Color Emoji.ttc tại đây , trong source code tham khảo có để file
Apple Color Emoji.ttc
tại thư mục vendor. - Ta cũng sửa lại source của gem gemoji tại máy sau khi đã cài đặt gem gemoji cho project.
- Mở file gemoji/lib/emoji/extractor.rb sửa giá trị của biến
EMOJI_TTF
về đường dẫn của fileApple Color Emoji.ttc
lưu tại thư mục vendor của project. - Chạy lại câu lệnh extract image.
bundle exec gemoji extract public/images/emoji
- Image sau khi extract được lưu tại thư mục public/images/emoji của source code tham khảo.
c. EmojiHelper:
- Xem danh sách các emoji tại đây.
- Tạo
EmojiHelper
, viết hàmemojify(content)
để thay thế các emoji có trong chuỗi content bằng hình ảnh tương ứng.
module EmojiHelper
def emojify content
h(content).to_str.gsub(/:([\w+-]+):/) do |match|
if emoji = Emoji.find_by_alias($1)
%(<img alt="#$1" src="#{image_path("emoji/#{emoji.image_filename}", skip_pipeline: true)}" style="vertical-align:middle" width="20" height="20" />)
else
match
end
end.html_safe if content.present?
end
end
- Ta tạo model post có 2 cột title và content để test hàm emojify.
rails generate scaffold post title:string content:string
- Sau khi chạy câu lệnh scaffold, ta tạo 1 bài post có nột dung là it's raining s and s!
- Ta gọi hàm
emojify(@post.content)
trong file app/views/posts/show.html.erb để hiển thị emoji có trong nội dung bài post. - Kết quả thu được.
d. CustomEmojiHelper:
- Theo như file db/emoji.json thì gem gemoji chỉ support các emoji của ios có version từ 10.2 trở xuống và không hỗ trợ 1 số emoji chỉ có ở android.
- Trong thực tế, khi user tạo bài post hoặc comment thì các ký tự emoji sẽ là các kí tự unicode chứ không phải các kí tự như trong emoji cheat sheet .
- Tạo
CustomEmojiHelper
và các hàm cần thiết để giải quyết vần đề trên. - Ta xem file emoji/character.rb của gem emoji, các hàm
image_filename()
,default_image_filename()
,self.hex_inspect(str)
,raw()
vàadd_unicode_alias(str)
. - Ta xem file lib/emoji.rb của gem emoji hàm
parse_data_file()
dòng 90, ta thấy emoji được tạo ra và gọi hàmadd_unicode_alias(uni)
, uni được truyền vào là kí tự unicode ứng với emoji được lưu trong file db/emoji.json. - Từ các hàm trên, ta có thể thấy từ kí tự unicode của emoji, ta có thể có được tên của image file ứng với emoji đó.
- Tiến hành cài đặt các hàm cần thiết cho
CustomEmojiHelper
.
a. Hàm is_emoji_char?(char)
- Xem danh sách các emoji và kí tự unicode tương ứng tại đây.
module CustomEmojiHelper
attr_accessor :emoji_char_codepoints
def is_emoji_char? char
@emoji_char_codepoints ||= (0x1F600...0x1F64F).to_a +
(0x1F300...0x1F5FF).to_a +
(0x1F680...0x1F6FF).to_a +
(0x2600...0x26FF).to_a +
(0x2700...0x27BF).to_a +
(0xFE00...0xFE0F).to_a +
(0x1F900...0x1F9FF).to_a +
(0x1F1E6...0x1F1FF).to_a
@emoji_char_codepoints.include? char.codepoints.first
end
end
b. Hàm emoji_image_url(char)
- Trong hàm này sử dụng image lấy từ repo loicpirez/EmojiExtractor.
- Các provider lần lượt là các thư mục hình trong thư mục emojipedia.org của repo.
def emoji_image_url char
providers = ["apple", "emoji-one", "emojidex", "emojipedia", "facebook", "google", "htc", "lg", "messenger", "microsoft", "mozilla", "samsung", "twitter"]
base_url = "https://raw.githubusercontent.com/loicpirez/EmojiExtractor/master/emojipedia.org"
image_name = char.codepoints.map { |c| c.to_s(16).rjust(4, '0') }.join('-').gsub(/-(fe0f|200d)\b/, '')
providers.each do |provider|
image_url = "#{base_url}/#{provider}/#{image_name}.png"
return image_url if url_exists?(image_url)
end
end
c. Hàm is_url_exists? url
- Có 1 số emoji chỉ có cho 1 provider mà không có cho provider khác, ta cần kiểm tra emoji_image_url của emoji ứng với provider có tồn tại hay không.
def url_exists? url
begin
uri = URI.parse url
request = Net::HTTP.new uri.host, uri.port
request.use_ssl = true
result = request.request_head uri.path
result.code == "200"
rescue
false
end
end
d. Hàm insert_emoji_image(content)
- Hàm thực hiện tìm các kí tự emoji trong chuỗi content và thay thế bằng thẻ
<img>
tương ứng với emoji đó, tương tự hàmemojify()
củaEmojiHelper
ở trên.
def insert_emoji_image content
emoji_chars = []
content.each_char do |char|
if is_emoji_char(char)
emoji_chars << char
end
end
emoji_chars.each do |emoji_char|
content.gsub! emoji_char, "<img src=#{emoji_image_url emoji_char} style='vertical-align:middle; width: 18px; height: 18px;' >"
end
content.html_safe
end
e. Nội dung CustomEmojiHelper:
module CustomEmojiHelper
attr_accessor :emoji_char_codepoints
def is_emoji_char? char
@emoji_char_codepoints ||= (0x1F600...0x1F64F).to_a +
(0x1F300...0x1F5FF).to_a +
(0x1F680...0x1F6FF).to_a +
(0x2600...0x26FF).to_a +
(0x2700...0x27BF).to_a +
(0xFE00...0xFE0F).to_a +
(0x1F900...0x1F9FF).to_a +
(0x1F1E6...0x1F1FF).to_a
@emoji_char_codepoints.include? char.codepoints.first
end
def emoji_image_url char
providers = ["apple", "emoji-one", "emojidex", "emojipedia", "facebook", "google", "htc", "lg", "messenger", "microsoft", "mozilla", "samsung", "twitter"]
base_url = "https://raw.githubusercontent.com/loicpirez/EmojiExtractor/master/emojipedia.org"
image_name = char.codepoints.map { |c| c.to_s(16).rjust(4, '0') }.join('-').gsub(/-(fe0f|200d)\b/, '')
providers.each do |provider|
image_url = "#{base_url}/#{provider}/#{image_name}.png"
return image_url if url_exists?(image_url)
end
end
def url_exists? url
begin
uri = URI.parse url
request = Net::HTTP.new uri.host, uri.port
request.use_ssl = true
result = request.request_head uri.path
result.code == "200"
rescue
false
end
end
def insert_emoji_image content
emoji_chars = []
content.each_char do |char|
if is_emoji_char?(char)
emoji_chars << char
end
end
emoji_chars.each do |emoji_char|
content.gsub! emoji_char, "<img src=#{emoji_image_url emoji_char} style='vertical-align:middle; width: 18px; height: 18px;' >"
end
content.html_safe
end
end
- Trong db/seeds.rb tạo 1 số bài post có nội dung chứa các emoji.
Post.create title: "title", content: "🧤🧥🧦👗👘👚👛👜👝🛍️<br>🎒👞👟👠👡👢👑👒🎩🎓"
Post.create title: "title", content: "🧦👗🧥👘👚👛🧥?"
Post.create title: "title", content: "😄😜😔🇰🇷😂😀😃😄😁😆🐶🐱🐭🐹🐰🍏🍎🍐🍊🍋⚽️🏀🏈⚾️🎾🚗🚕🚙🚌🚎"
Post.create title: "title", content: "🧥😊🌏😀😆😗🐵🦊🐴🍇🍎🍅🚎"
- Gọi hàm
insert_emoji_image(content)
và kiểm tra kết quả thu được. - Trước khi gọi hàm
- Sau khi gọi hàm
f. Source code tham khảo:
All rights reserved