Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #49 from github/edit-emoji

Add API for adding new / editing existing emoji
  • Loading branch information...
commit 3b65ee2f15047fa4273f2ee26ad4c530a7898aa8 2 parents e9480a9 + 0bea2df
@mislav mislav authored
View
43 README.md
@@ -78,3 +78,46 @@ Translate emoji names to unicode and vice versa.
>> Emoji.find_by_unicode("\u{1f431}").name
=> "cat"
```
+
+Adding new emoji
+----------------
+
+You can add new emoji characters to the `Emoji.all` list:
+
+```ruby
+emoji = Emoji.create("music") do |char|
+ char.add_alias "song"
+ char.add_unicode_alias "\u{266b}"
+ char.add_tag "notes"
+end
+
+emoji.name #=> "music"
+emoji.raw #=> "♫"
+emoji.image_filename #=> "unicode/266b.png"
+
+# Creating custom emoji (no Unicode aliases):
+emoji = Emoji.create("music") do |char|
+ char.add_tag "notes"
+end
+
+emoji.custom? #=> true
+emoji.image_filename #=> "music.png"
+```
+
+As you create new emoji, you must ensure that you also create and put the images
+they reference by their `image_filename` to your assets directory.
+
+For existing emojis, you can edit the list of aliases or add new tags in an edit block:
+
+```ruby
+emoji = Emoji.find_by_alias "musical_note"
+
+Emoji.edit_emoji(emoji) do |char|
+ char.add_alias "music"
+ char.add_unicode_alias "\u{266b}"
+ char.add_tag "notes"
+end
+
+Emoji.find_by_alias "music" #=> emoji
+Emoji.find_by_unicode "\u{266b}" #=> emoji
+```
View
9 db/dump.rb
@@ -52,17 +52,18 @@ def add_reference(code)
trap(:PIPE) { abort }
items = []
+variation = Emoji::VARIATION_SELECTOR_16
for emoji in Emoji.all
- unicodes = emoji.unicode_aliases
- unicodes = unicodes[1..-1] if emoji.variation?
+ unicodes = emoji.unicode_aliases.dup
item = {}
unless emoji.custom?
- variation_codepoint = Emoji::Character::VARIATION_SELECTOR_16.codepoints[0]
+ variation_codepoint = variation.codepoints[0]
chars = emoji.raw.codepoints.map { |code| UnicodeCharacter.fetch(code) unless code == variation_codepoint }.compact
- item[:emoji] = emoji.raw
+ unicodes.select { |u| u.index(variation) }.each { |u| unicodes.delete(u.sub(variation, '')) }
+ item[:emoji] = unicodes.shift
item[:unicodes] = unicodes if unicodes.any?
item[:description] = chars.map(&:description).join(' + ')
end
View
75 lib/emoji.rb
@@ -15,7 +15,36 @@ def images_path
end
def all
- @all ||= parse_data_file
+ return @all if defined? @all
+ @all = []
+ parse_data_file
+ @all
+ end
+
+ # Public: Initialize an Emoji::Character instance and yield it to the block.
+ # The character is added to the `Emoji.all` set.
+ def create(name)
+ emoji = Emoji::Character.new(name)
+ self.all << edit_emoji(emoji) { yield emoji if block_given? }
+ emoji
+ end
+
+ # Public: Yield an emoji to the block and update the indices in case its
+ # aliases or unicode_aliases lists changed.
+ def edit_emoji(emoji)
+ @names_index ||= Hash.new
+ @unicodes_index ||= Hash.new
+
+ yield emoji
+
+ emoji.aliases.each do |name|
+ @names_index[name] = emoji
+ end
+ emoji.unicode_aliases.each do |unicode|
+ @unicodes_index[unicode] = emoji
+ end
+
+ emoji
end
def find_by_alias(name)
@@ -35,40 +64,34 @@ def find_by_unicode(unicode)
end
private
- def create_index
- index = Hash.new { |hash, key| hash[key] = [] }
- yield index
- index
- end
+ VARIATION_SELECTOR_16 = "\u{fe0f}".freeze
def parse_data_file
raw = File.open(data_file, 'r:UTF-8') { |data| JSON.parse(data.read) }
- raw.map do |raw_emoji|
- char = Emoji::Character.new(raw_emoji['emoji'])
- raw_emoji.fetch('aliases').each { |name| char.add_alias(name) }
- raw_emoji.fetch('unicodes', []).each { |uni| char.add_unicode_alias(uni) }
- raw_emoji.fetch('tags').each { |tag| char.add_tag(tag) }
- char
+ raw.each do |raw_emoji|
+ self.create(nil) do |emoji|
+ raw_emoji.fetch('aliases').each { |name| emoji.add_alias(name) }
+ unicodes = Array(raw_emoji['emoji']) + raw_emoji.fetch('unicodes', [])
+ unicodes.each { |uni|
+ emoji.add_unicode_alias(uni)
+ # Automatically add a representation of this emoji without the variation
+ # selector to unicode aliases:
+ if uni.index(VARIATION_SELECTOR_16)
+ emoji.add_unicode_alias(uni.sub(VARIATION_SELECTOR_16, ''))
+ end
+ }
+ raw_emoji.fetch('tags').each { |tag| emoji.add_tag(tag) }
+ end
end
end
def names_index
- @names_index ||= create_index do |mapping|
- all.each do |emoji|
- emoji.aliases.each do |name|
- mapping[name] = emoji
- end
- end
- end
+ all unless defined? @all
+ @names_index
end
def unicodes_index
- @unicodes_index ||= create_index do |mapping|
- all.each do |emoji|
- emoji.unicode_aliases.each do |unicode|
- mapping[unicode] = emoji
- end
- end
- end
+ all unless defined? @all
+ @unicodes_index
end
end
View
20 lib/emoji/character.rb
@@ -1,7 +1,5 @@
module Emoji
class Character
- VARIATION_SELECTOR_16 = "\u{fe0f}".freeze
-
# Inspect individual Unicode characters in a string by dumping its
# codepoints in hexadecimal format.
def self.hex_inspect(str)
@@ -20,9 +18,7 @@ def add_alias(name)
aliases << name
end
- # A list of Unicode strings that uniquely refer to this emoji. By default,
- # this list includes the emoji's Unicode representation without the
- # variation selector character.
+ # A list of Unicode strings that uniquely refer to this emoji.
attr_reader :unicode_aliases
# Raw Unicode string for an emoji. Nil if emoji is non-standard.
@@ -40,14 +36,10 @@ def add_tag(tag)
tags << tag
end
- def initialize(raw)
- @aliases = []
- @unicode_aliases = Array(raw)
+ def initialize(name)
+ @aliases = Array(name)
+ @unicode_aliases = []
@tags = []
-
- # Automatically add a representation of this emoji without the variation
- # selector to unicode aliases:
- add_unicode_alias(raw.sub(VARIATION_SELECTOR_16, '')) if variation?
end
def inspect
@@ -55,10 +47,6 @@ def inspect
%(#<#{self.class.name}:#{name}#{hex}>)
end
- def variation?
- !custom? && raw.index(VARIATION_SELECTOR_16)
- end
-
def hex_inspect
self.class.hex_inspect(raw)
end
View
60 test/emoji_test.rb
@@ -84,4 +84,64 @@ class EmojiTest < TestCase
assert custom_names.include?("shipit")
assert !custom_names.include?("+1")
end
+
+ test "create" do
+ emoji = Emoji.create("music") do |char|
+ char.add_unicode_alias "\u{266b}"
+ char.add_unicode_alias "\u{266a}"
+ char.add_tag "notes"
+ char.add_tag "eighth"
+ end
+
+ begin
+ assert_equal emoji, Emoji.all.last
+ assert_equal emoji, Emoji.find_by_alias("music")
+ assert_equal emoji, Emoji.find_by_unicode("\u{266a}")
+ assert_equal emoji, Emoji.find_by_unicode("\u{266b}")
+
+ assert_equal "\u{266b}", emoji.raw
+ assert_equal "unicode/266b.png", emoji.image_filename
+ assert_equal %w[music], emoji.aliases
+ assert_equal %w[notes eighth], emoji.tags
+ ensure
+ Emoji.all.pop
+ end
+ end
+
+ test "create without block" do
+ emoji = Emoji.create("music")
+
+ begin
+ assert_equal emoji, Emoji.find_by_alias("music")
+ assert_equal [], emoji.unicode_aliases
+ assert_equal [], emoji.tags
+ assert_equal "music.png", emoji.image_filename
+ ensure
+ Emoji.all.pop
+ end
+ end
+
+ test "edit" do
+ emoji = Emoji.find_by_alias("weary")
+
+ emoji = Emoji.edit_emoji(emoji) do |char|
+ char.add_alias "whining"
+ char.add_unicode_alias "\u{1f629}\u{266a}"
+ char.add_tag "complaining"
+ end
+
+ begin
+ assert_equal emoji, Emoji.find_by_alias("weary")
+ assert_equal emoji, Emoji.find_by_alias("whining")
+ assert_equal emoji, Emoji.find_by_unicode("\u{1f629}")
+ assert_equal emoji, Emoji.find_by_unicode("\u{1f629}\u{266a}")
+
+ assert_equal %w[weary whining], emoji.aliases
+ assert_includes emoji.tags, "complaining"
+ ensure
+ emoji.aliases.pop
+ emoji.unicode_aliases.pop
+ emoji.tags.pop
+ end
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.