emoji-datasource 14.0.0 → 14.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b3935f8318904fee0e0c3e662d843c7720e6ec2e7df4dafe98ffe7365d3f6236
4
- data.tar.gz: a7c9b43189f238363cf275d68037970d5f3d5f03c379e6415bab44bab25ff938
3
+ metadata.gz: b821544f15170c9489e0ce8938978549829e3c925d3ec6444dfacb7c125b94ca
4
+ data.tar.gz: bf4e9c21d3c5ea9de80132de4aa56bfec68c705aba979863151d650facc73f77
5
5
  SHA512:
6
- metadata.gz: 2049e3e19cb85aa80dc0fe47604d3f715b02977d50cdd9cd345aecdd949f7dbaca7cc15c7a0e26078bc04803fe3c3cc4c1fd63e6f2822e3cf00cf2ed161a3aaa
7
- data.tar.gz: ee10a8cb1a4cb899a659700363956aa97ab3994c74ce563fa7cd461a18e2ab92de669163e5c25df20d2c780e332084b4ef402127798d4bd78e32ecbbd130fce8
6
+ metadata.gz: 03d5041a86c4d7bccde94965634abffd3194c7cc3dcfa70e1de6f573ea1b6d444c6382cc0275b88165597247dd1e97f1ced2050ca671c51183fcb62412a8dcea
7
+ data.tar.gz: 994db50c5e4221bf51ed491d108d0b3fb48dea1fae2837d3129d39586d8eb7d080e0423bec5aac775eba4ffc0360299bd20cb64b607f4333c0b9f36a6b2805f2
data/README.md CHANGED
@@ -22,6 +22,21 @@ Find emoji by short name
22
22
 
23
23
  ```ruby
24
24
  EmojiDatasource.find_by_short_name('+1')
25
+ #=> EmojiDatasource::Emoji: :+1: (👍)
26
+ ```
27
+
28
+ Find emoji by raw string:
29
+
30
+ ```ruby
31
+ EmojiDatasource.find_by_char('👍🏾')
32
+ #=> EmojiDatasource::Emoji: :+1::skin-tone-5: (👍🏾)
33
+ ```
34
+
35
+ Find emoji by unicode hex character code:
36
+
37
+ ```ruby
38
+ EmojiDatasource.find_by_unified("1F469-200D-2764-FE0F-200D-1F468")
39
+ #=> EmojiDatasource::Emoji: :woman-heart-man: (👩‍❤️‍👨)
25
40
  ```
26
41
 
27
42
  Convert emoji short name to character
@@ -33,9 +48,17 @@ EmojiDatasource.short_name_to_char('+1') # => 👍
33
48
  this also supports skin variations
34
49
 
35
50
  ```ruby
36
- EmojiDatasource.short_name_to_char('+1::skin-tone-2') # => 👍
51
+ EmojiDatasource.short_name_to_char('+1::skin-tone-2') # => 👍🏻
37
52
  ```
38
53
 
54
+ Get base emoji for skin variation:
55
+
56
+ ```ruby
57
+ emoji = EmojiDatasource.find_by_short_name(':+1::skin-tone-5:')
58
+ #=> EmojiDatasource::Emoji: :+1::skin-tone-5: (👍🏾)
59
+ emoji.base
60
+ #=> EmojiDatasource::Emoji: :+1: (👍)
61
+ ```
39
62
 
40
63
  ## Supported Ruby Versions
41
64
 
@@ -2,38 +2,75 @@
2
2
 
3
3
  module EmojiDatasource
4
4
  class Emoji
5
- attr_reader :data
5
+ attr_reader :data, :unified
6
6
 
7
- def initialize(data)
7
+ def initialize(data, variation: nil)
8
8
  @data = data
9
+ @variation = variation
10
+ @unified = variation ? @data.dig('skin_variations', variation, 'unified') : @data['unified']
9
11
  end
10
12
 
13
+ # Raw emoji string
11
14
  def to_char
12
- EmojiDatasource.unified_to_char(data[:unified])
15
+ EmojiDatasource.unified_to_char(unified)
13
16
  end
14
17
 
15
- def skin_variations
16
- return unless @data[:skin_variations]
18
+ # Official emoji name (pretty long)
19
+ def name
20
+ return @data['name'] unless @variation
17
21
 
18
- @data[:skin_variations].transform_keys(&:to_s)
22
+ "#{@data['name']} (#{variation_emojis.map(&:name).join(', ')})"
23
+ end
24
+
25
+ # Short code that often can be used to find emoji in pickers and chat apps
26
+ def short_name
27
+ return @data['short_name'] unless @variation
28
+
29
+ "#{@data['short_name']}::#{variation_emojis.map(&:short_name).join('::')}"
30
+ end
31
+
32
+ # All known short names (base +short_name+ and maybe some aliases)
33
+ def short_names
34
+ return @data['short_names'] unless @variation
35
+
36
+ @data['short_names'].map do |short_name|
37
+ "#{short_name}::#{variation_emojis.map(&:short_name).join('::')}"
38
+ end
39
+ end
40
+
41
+ # All known skin tone variations
42
+ def variations
43
+ return @variations = [] if @variation
44
+
45
+ @variations ||= @data.fetch('skin_variations', {}).each_key.map do |key|
46
+ self.class.new(data, variation: key)
47
+ end
48
+ end
49
+
50
+ # Base emoji, without variations applied.
51
+ # E.g. for `:+1::skin-tone-2:` base will be just `:+1:`
52
+ def base
53
+ return self unless @variation
54
+
55
+ EmojiDatasource.find_by_unified(@data['unified'])
19
56
  end
20
57
 
21
58
  def method_missing(method_name, *arguments, &block)
22
- if @data.key?(method_name)
23
- @data[method_name]
59
+ if @data.key?(method_name.to_s)
60
+ @data[method_name.to_s]
24
61
  else
25
62
  super
26
63
  end
27
64
  end
28
65
 
29
66
  def respond_to_missing?(method_name, include_private = false)
30
- return true if @data.key?(method_name)
67
+ return true if @data.key?(method_name.to_s)
31
68
 
32
69
  super
33
70
  end
34
71
 
35
72
  def inspect
36
- "#{self.class.name}:#{short_name}"
73
+ "#{self.class.name}: :#{short_name}: (#{to_char})"
37
74
  end
38
75
 
39
76
  def to_s
@@ -47,5 +84,15 @@ module EmojiDatasource
47
84
  def to_json(**args)
48
85
  @data.to_json(**args)
49
86
  end
87
+
88
+ private
89
+
90
+ def variation_emojis
91
+ return [] unless @variation
92
+
93
+ @variation.split('-').map do |unified|
94
+ EmojiDatasource.find_by_unified(unified)
95
+ end
96
+ end
50
97
  end
51
98
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EmojiDatasource
4
- VERSION = '14.0.0'
4
+ VERSION = '14.0.1'
5
5
  end
@@ -4,23 +4,50 @@ require 'json'
4
4
 
5
5
  require_relative 'emoji_datasource/version'
6
6
  require_relative 'emoji_datasource/emoji'
7
- require_relative 'emoji_datasource/short_name_to_char'
8
7
 
9
8
  module EmojiDatasource
10
9
  class Error < StandardError; end
11
10
 
12
11
  EMOJI_DATA_PATH = File.join(__dir__, '..', 'vendor', 'emoji-datasource', 'emoji.json')
13
12
 
13
+ # @example
14
+ # short_name_to_char('+1') #=> "👍"
14
15
  def self.short_name_to_char(name)
15
- EmojiDatasource::ShortNameToChar.generate(name)
16
+ find_by_short_name(name)&.to_char
16
17
  end
17
18
 
19
+ # Finds emoji by short code (e.g. `+1`, `:+1:`, `:+1::skin-tone-5:`)
20
+ # @param name [String] short code with or without wrapping colons.
21
+ # @return [EmojiDatasource::Emoji] if there is an emoji matching +name+
22
+ # @return [nil] if there are no emojis matching +name+
23
+ # @example
24
+ # find_by_short_name('+1') #=> EmojiDatasource::Emoji: :+1: (👍)
18
25
  def self.find_by_short_name(name)
19
26
  return unless name
20
27
 
21
- data.detect do |emoji|
22
- emoji.short_name == name || emoji.short_names.include?(name)
23
- end
28
+ name = name.delete_prefix(':').delete_suffix(':') # Allow to find `+1` by `:+1:`
29
+ name.delete_suffix!('::skin-tone-1') # special case for default skin tone
30
+ short_name_lookup_map[name]
31
+ end
32
+
33
+ # Finds emoji by unified hex representation of Unicode codepoints
34
+ # @param unified [String] Dash separated hexadecimal Unicode character codes for a single emoji
35
+ # @return [EmojiDatasource::Emoji] if given Unicode codepoints is a known emoji
36
+ # @return [nil] if there are no emojis with given codepoints in the dataset
37
+ # @example
38
+ # short_name_to_char('1F44D') #=> EmojiDatasource::Emoji: :+1: (👍)
39
+ def self.find_by_unified(unified)
40
+ unified_lookup_map[unified.upcase]
41
+ end
42
+
43
+ # Find emoji object by raw Unicode string with a single emoji in it
44
+ # @param raw_emoji [String] Single emoji
45
+ # @return [EmojiDatasource::Emoji] if given string contains a single known emoji
46
+ # @return [nil] if there are no such emoji in the dataset
47
+ # @example
48
+ # find_by_char('👍') #=> EmojiDatasource::Emoji: :+1: (👍)
49
+ def self.find_by_char(raw_emoji)
50
+ find_by_unified(char_to_unified(raw_emoji))
24
51
  end
25
52
 
26
53
  def self.unified_to_char(unified_name)
@@ -29,10 +56,38 @@ module EmojiDatasource
29
56
  unified_name.split('-').map(&:hex).pack('U*')
30
57
  end
31
58
 
59
+ def self.char_to_unified(raw_emoji)
60
+ return unless raw_emoji
61
+
62
+ raw_emoji.unpack('U*').map { |c| c.to_s(16).upcase }.join('-')
63
+ end
64
+
32
65
  def self.data
33
- @data ||= JSON.parse(File.read(EMOJI_DATA_PATH), symbolize_names: true)
66
+ @data ||= JSON.parse(File.read(EMOJI_DATA_PATH))
34
67
  .map { |emoji_data| EmojiDatasource::Emoji.new(emoji_data) }
35
68
  end
69
+
70
+ # Utility hash map to search by emoji short code, including variants
71
+ # @api private
72
+ def self.short_name_lookup_map
73
+ @short_name_lookup_map ||= data.each_with_object({}) do |emoji, result|
74
+ emoji.short_names.each { |short_name| result[short_name] = emoji }
75
+ emoji.variations.each do |emoji_variant|
76
+ emoji_variant.short_names.each { |short_name| result[short_name] = emoji_variant }
77
+ end
78
+ end
79
+ end
80
+
81
+ # Utility hash map to search by unicode character sequence hex codes, including variants
82
+ # @api private
83
+ def self.unified_lookup_map
84
+ @unified_lookup_map ||= data.each_with_object({}) do |emoji, result|
85
+ result[emoji.unified] = emoji
86
+ emoji.variations.each do |emoji_variant|
87
+ result[emoji_variant.unified] = emoji_variant
88
+ end
89
+ end
90
+ end
36
91
  end
37
92
 
38
93
  # Preload emojies on startup
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: emoji-datasource
3
3
  version: !ruby/object:Gem::Version
4
- version: 14.0.0
4
+ version: 14.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justas Palumickas
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-02-14 00:00:00.000000000 Z
11
+ date: 2023-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -104,7 +104,6 @@ files:
104
104
  - lib/emoji-datasource.rb
105
105
  - lib/emoji_datasource.rb
106
106
  - lib/emoji_datasource/emoji.rb
107
- - lib/emoji_datasource/short_name_to_char.rb
108
107
  - lib/emoji_datasource/version.rb
109
108
  - package.json
110
109
  - vendor/emoji-datasource/emoji.json
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EmojiDatasource
4
- class ShortNameToChar
5
- def self.generate(name)
6
- new(name).call
7
- end
8
-
9
- attr_reader :short_name
10
-
11
- def initialize(short_name)
12
- @short_name = short_name
13
- end
14
-
15
- def call
16
- return unless short_name
17
- return EmojiDatasource.find_by_short_name(short_name)&.to_char unless skin_tone_matches
18
-
19
- emoji = EmojiDatasource.find_by_short_name(skin_tone_matches[1])
20
- return unless emoji
21
- return emoji.to_char if skin_tone_level == 1
22
-
23
- char_with_skin_tone(emoji)
24
- end
25
-
26
- private
27
-
28
- def char_with_skin_tone(emoji)
29
- return unless skin_tone_emoji
30
-
31
- skin_variation = emoji.skin_variations && emoji.skin_variations[skin_tone_emoji.unified]
32
- return unless skin_variation
33
-
34
- EmojiDatasource.unified_to_char(skin_variation[:unified])
35
- end
36
-
37
- def skin_tone_emoji
38
- EmojiDatasource.find_by_short_name("skin-tone-#{skin_tone_level}")
39
- end
40
-
41
- def skin_tone_level
42
- skin_tone_matches[2].to_i
43
- end
44
-
45
- def skin_tone_matches
46
- short_name.match(/:?(.+)::skin-tone-(\d+):?/)
47
- end
48
- end
49
- end