emoji-datasource 14.0.0 → 14.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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