gemoji 3.0.1 → 4.0.0.rc3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/LICENSE +22 -0
- data/README.md +1 -16
- data/db/emoji.json +11832 -7054
- data/lib/emoji.rb +56 -50
- data/lib/emoji/character.rb +2 -0
- data/lib/gemoji.rb +2 -0
- metadata +12 -34
- data/bin/gemoji +0 -5
- data/db/Category-Emoji.json +0 -71
- data/images/basecamp.png +0 -0
- data/images/basecampy.png +0 -0
- data/images/bowtie.png +0 -0
- data/images/feelsgood.png +0 -0
- data/images/finnadie.png +0 -0
- data/images/goberserk.png +0 -0
- data/images/godmode.png +0 -0
- data/images/hurtrealbad.png +0 -0
- data/images/neckbeard.png +0 -0
- data/images/octocat.png +0 -0
- data/images/rage1.png +0 -0
- data/images/rage2.png +0 -0
- data/images/rage3.png +0 -0
- data/images/rage4.png +0 -0
- data/images/shipit.png +0 -0
- data/images/suspect.png +0 -0
- data/images/trollface.png +0 -0
- data/lib/emoji/cli.rb +0 -68
- data/lib/emoji/extractor.rb +0 -190
data/lib/emoji.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
require 'emoji/character'
|
3
5
|
require 'json'
|
4
6
|
|
@@ -9,14 +11,6 @@ module Emoji
|
|
9
11
|
File.expand_path('../../db/emoji.json', __FILE__)
|
10
12
|
end
|
11
13
|
|
12
|
-
def apple_palette_file
|
13
|
-
File.expand_path('../../db/Category-Emoji.json', __FILE__)
|
14
|
-
end
|
15
|
-
|
16
|
-
def images_path
|
17
|
-
File.expand_path("../../images", __FILE__)
|
18
|
-
end
|
19
|
-
|
20
14
|
def all
|
21
15
|
return @all if defined? @all
|
22
16
|
@all = []
|
@@ -24,17 +18,6 @@ module Emoji
|
|
24
18
|
@all
|
25
19
|
end
|
26
20
|
|
27
|
-
def apple_palette
|
28
|
-
return @apple_palette if defined? @apple_palette
|
29
|
-
data = File.open(apple_palette_file, 'r:UTF-8') { |f| JSON.parse(f.read) }
|
30
|
-
@apple_palette = data.fetch('EmojiDataArray').each_with_object({}) do |group, all|
|
31
|
-
title = group.fetch('CVDataTitle').split('-', 2)[1]
|
32
|
-
all[title] = group.fetch('CVCategoryData').fetch('Data').split(',').map do |raw|
|
33
|
-
TEXT_GLYPHS.include?(raw) ? raw + VARIATION_SELECTOR_16 : raw
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
21
|
# Public: Initialize an Emoji::Character instance and yield it to the block.
|
39
22
|
# The character is added to the `Emoji.all` set.
|
40
23
|
def create(name)
|
@@ -73,45 +56,68 @@ module Emoji
|
|
73
56
|
|
74
57
|
private
|
75
58
|
VARIATION_SELECTOR_16 = "\u{fe0f}".freeze
|
76
|
-
ZERO_WIDTH_JOINER = "\u{200d}".freeze
|
77
|
-
FEMALE_SYMBOL = "\u{2640}".freeze
|
78
|
-
MALE_SYMBOL = "\u{2642}".freeze
|
79
59
|
|
80
|
-
#
|
81
|
-
TEXT_GLYPHS = [
|
60
|
+
# Characters which must have VARIATION_SELECTOR_16 to render as color emoji:
|
61
|
+
TEXT_GLYPHS = [
|
62
|
+
"\u{1f237}", # Japanese “monthly amount” button
|
63
|
+
"\u{1f202}", # Japanese “service charge” button
|
64
|
+
"\u{1f170}", # A button (blood type)
|
65
|
+
"\u{1f171}", # B button (blood type)
|
66
|
+
"\u{1f17e}", # O button (blood type)
|
67
|
+
"\u{00a9}", # copyright
|
68
|
+
"\u{00ae}", # registered
|
69
|
+
"\u{2122}", # trade mark
|
70
|
+
"\u{3030}", # wavy dash
|
71
|
+
].freeze
|
72
|
+
|
73
|
+
private_constant :VARIATION_SELECTOR_16, :TEXT_GLYPHS
|
82
74
|
|
83
75
|
def parse_data_file
|
84
|
-
data = File.open(data_file, 'r:UTF-8')
|
85
|
-
|
86
|
-
|
87
|
-
raw_emoji.fetch('aliases').each { |name| emoji.add_alias(name) }
|
88
|
-
if raw = raw_emoji['emoji']
|
89
|
-
unicodes = [raw, raw.sub(VARIATION_SELECTOR_16, '') + VARIATION_SELECTOR_16].uniq
|
90
|
-
unicodes.each { |uni| emoji.add_unicode_alias(uni) }
|
91
|
-
end
|
92
|
-
raw_emoji.fetch('tags').each { |tag| emoji.add_tag(tag) }
|
76
|
+
data = File.open(data_file, 'r:UTF-8') do |file|
|
77
|
+
JSON.parse(file.read, symbolize_names: true)
|
78
|
+
end
|
93
79
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
80
|
+
if "".respond_to?(:-@)
|
81
|
+
# Ruby >= 2.3 this is equivalent to .freeze
|
82
|
+
# Ruby >= 2.5 this will freeze and dedup
|
83
|
+
dedup = lambda { |str| -str }
|
84
|
+
else
|
85
|
+
dedup = lambda { |str| str.freeze }
|
86
|
+
end
|
87
|
+
|
88
|
+
append_unicode = lambda do |emoji, raw|
|
89
|
+
unless TEXT_GLYPHS.include?(raw) || emoji.unicode_aliases.include?(raw)
|
90
|
+
emoji.add_unicode_alias(dedup.call(raw))
|
98
91
|
end
|
99
92
|
end
|
100
93
|
|
101
|
-
# Add an explicit gendered variant to emoji that historically imply a gender
|
102
94
|
data.each do |raw_emoji|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
95
|
+
self.create(nil) do |emoji|
|
96
|
+
raw_emoji.fetch(:aliases).each { |name| emoji.add_alias(dedup.call(name)) }
|
97
|
+
if raw = raw_emoji[:emoji]
|
98
|
+
append_unicode.call(emoji, raw)
|
99
|
+
start_pos = 0
|
100
|
+
while found_index = raw.index(VARIATION_SELECTOR_16, start_pos)
|
101
|
+
# register every variant where one VARIATION_SELECTOR_16 is removed
|
102
|
+
raw_alternate = raw.dup
|
103
|
+
raw_alternate[found_index] = ""
|
104
|
+
append_unicode.call(emoji, raw_alternate)
|
105
|
+
start_pos = found_index + 1
|
106
|
+
end
|
107
|
+
if start_pos > 0
|
108
|
+
# register a variant with all VARIATION_SELECTOR_16 removed
|
109
|
+
append_unicode.call(emoji, raw.gsub(VARIATION_SELECTOR_16, ""))
|
110
|
+
else
|
111
|
+
# register a variant where VARIATION_SELECTOR_16 is added
|
112
|
+
append_unicode.call(emoji, "#{raw}#{VARIATION_SELECTOR_16}")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
raw_emoji.fetch(:tags).each { |tag| emoji.add_tag(dedup.call(tag)) }
|
116
|
+
|
117
|
+
emoji.category = dedup.call(raw_emoji[:category])
|
118
|
+
emoji.description = dedup.call(raw_emoji[:description])
|
119
|
+
emoji.unicode_version = dedup.call(raw_emoji[:unicode_version])
|
120
|
+
emoji.ios_version = dedup.call(raw_emoji[:ios_version])
|
115
121
|
end
|
116
122
|
end
|
117
123
|
end
|
data/lib/emoji/character.rb
CHANGED
data/lib/gemoji.rb
CHANGED
metadata
CHANGED
@@ -1,53 +1,32 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gemoji
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0.rc3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-07-26 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description: Character information and metadata for
|
13
|
+
description: Character information and metadata for Unicode emoji.
|
14
14
|
email: support@github.com
|
15
|
-
executables:
|
16
|
-
- gemoji
|
15
|
+
executables: []
|
17
16
|
extensions: []
|
18
17
|
extra_rdoc_files: []
|
19
18
|
files:
|
19
|
+
- LICENSE
|
20
20
|
- README.md
|
21
|
-
- bin/gemoji
|
22
|
-
- db/Category-Emoji.json
|
23
21
|
- db/emoji.json
|
24
|
-
- images/basecamp.png
|
25
|
-
- images/basecampy.png
|
26
|
-
- images/bowtie.png
|
27
|
-
- images/feelsgood.png
|
28
|
-
- images/finnadie.png
|
29
|
-
- images/goberserk.png
|
30
|
-
- images/godmode.png
|
31
|
-
- images/hurtrealbad.png
|
32
|
-
- images/neckbeard.png
|
33
|
-
- images/octocat.png
|
34
|
-
- images/rage1.png
|
35
|
-
- images/rage2.png
|
36
|
-
- images/rage3.png
|
37
|
-
- images/rage4.png
|
38
|
-
- images/shipit.png
|
39
|
-
- images/suspect.png
|
40
|
-
- images/trollface.png
|
41
22
|
- lib/emoji.rb
|
42
23
|
- lib/emoji/character.rb
|
43
|
-
- lib/emoji/cli.rb
|
44
|
-
- lib/emoji/extractor.rb
|
45
24
|
- lib/gemoji.rb
|
46
25
|
homepage: https://github.com/github/gemoji
|
47
26
|
licenses:
|
48
27
|
- MIT
|
49
28
|
metadata: {}
|
50
|
-
post_install_message:
|
29
|
+
post_install_message:
|
51
30
|
rdoc_options: []
|
52
31
|
require_paths:
|
53
32
|
- lib
|
@@ -58,13 +37,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
58
37
|
version: '1.9'
|
59
38
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
39
|
requirements:
|
61
|
-
- - "
|
40
|
+
- - ">"
|
62
41
|
- !ruby/object:Gem::Version
|
63
|
-
version:
|
42
|
+
version: 1.3.1
|
64
43
|
requirements: []
|
65
|
-
|
66
|
-
|
67
|
-
signing_key:
|
44
|
+
rubygems_version: 3.0.3
|
45
|
+
signing_key:
|
68
46
|
specification_version: 4
|
69
|
-
summary:
|
47
|
+
summary: Unicode emoji library
|
70
48
|
test_files: []
|
data/bin/gemoji
DELETED
data/db/Category-Emoji.json
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"EmojiDataArray" : [
|
3
|
-
{
|
4
|
-
"CVDataTitle" : "EmojiCategory-People",
|
5
|
-
"CVCategoryImage" : "Emoji-HumanImage",
|
6
|
-
"CVCategoryData" : {
|
7
|
-
"CVSkipNullGlyphs" : false,
|
8
|
-
"Data" : "😀,😃,😄,😁,😆,😅,😂,🤣,☺️,😊,😇,🙂,🙃,😉,😌,😍,😘,😗,😙,😚,😋,😜,😝,😛,🤑,🤗,🤓,😎,🤡,🤠,😏,😒,😞,😔,😟,😕,🙁,☹️,😣,😖,😫,😩,😤,😠,😡,😶,😐,😑,😯,😦,😧,😮,😲,😵,😳,😱,😨,😰,😢,😥,🤤,😭,😓,😪,😴,🙄,🤔,🤥,😬,🤐,🤢,🤧,😷,🤒,🤕,😈,👿,👹,👺,💩,👻,💀,☠️,👽,👾,🤖,🎃,😺,😸,😹,😻,😼,😽,🙀,😿,😾,👐,🙌,👏,🙏,🤝,👍,👎,👊,✊,🤛,🤜,🤞,✌️,🤘,👌,👈,👉,👆,👇,☝️,✋,🤚,🖐,🖖,👋,🤙,💪,🖕,✍️,🤳,💅,💍,💄,💋,👄,👅,👂,👃,👣,👁,👀,🗣,👤,👥,👶,👦,👧,👨,👩,👱♀️,👱,👴,👵,👲,👳♀️,👳,👮♀️,👮,👷♀️,👷,💂♀️,💂,🕵️♀️,🕵️,👩⚕️,👨⚕️,👩🌾,👨🌾,👩🍳,👨🍳,👩🎓,👨🎓,👩🎤,👨🎤,👩🏫,👨🏫,👩🏭,👨🏭,👩💻,👨💻,👩💼,👨💼,👩🔧,👨🔧,👩🔬,👨🔬,👩🎨,👨🎨,👩🚒,👨🚒,👩✈️,👨✈️,👩🚀,👨🚀,👩⚖️,👨⚖️,🤶,🎅,👸,🤴,👰,🤵,👼,🤰,🙇♀️,🙇,💁,💁♂️,🙅,🙅♂️,🙆,🙆♂️,🙋,🙋♂️,🤦♀️,🤦♂️,🤷♀️,🤷♂️,🙎,🙎♂️,🙍,🙍♂️,💇,💇♂️,💆,💆♂️,🕴,💃,🕺,👯,👯♂️,🚶♀️,🚶,🏃♀️,🏃,👫,👭,👬,💑,👩❤️👩,👨❤️👨,💏,👩❤️💋👩,👨❤️💋👨,👪,👨👩👧,👨👩👧👦,👨👩👦👦,👨👩👧👧,👩👩👦,👩👩👧,👩👩👧👦,👩👩👦👦,👩👩👧👧,👨👨👦,👨👨👧,👨👨👧👦,👨👨👦👦,👨👨👧👧,👩👦,👩👧,👩👧👦,👩👦👦,👩👧👧,👨👦,👨👧,👨👧👦,👨👦👦,👨👧👧,👚,👕,👖,👔,👗,👙,👘,👠,👡,👢,👞,👟,👒,🎩,🎓,👑,⛑,🎒,👝,👛,👜,💼,👓,🕶,🌂,☂️"
|
9
|
-
}
|
10
|
-
},
|
11
|
-
{
|
12
|
-
"CVDataTitle" : "EmojiCategory-Nature",
|
13
|
-
"CVCategoryImage" : "Emoji-NatureImage",
|
14
|
-
"CVCategoryData" : {
|
15
|
-
"CVSkipNullGlyphs" : false,
|
16
|
-
"Data" : "🐶,🐱,🐭,🐹,🐰,🦊,🐻,🐼,🐨,🐯,🦁,🐮,🐷,🐽,🐸,🐵,🙈,🙉,🙊,🐒,🐔,🐧,🐦,🐤,🐣,🐥,🦆,🦅,🦉,🦇,🐺,🐗,🐴,🦄,🐝,🐛,🦋,🐌,🐚,🐞,🐜,🕷,🕸,🐢,🐍,🦎,🦂,🦀,🦑,🐙,🦐,🐠,🐟,🐡,🐬,🦈,🐳,🐋,🐊,🐆,🐅,🐃,🐂,🐄,🦌,🐪,🐫,🐘,🦏,🦍,🐎,🐖,🐐,🐏,🐑,🐕,🐩,🐈,🐓,🦃,🕊,🐇,🐁,🐀,🐿,🐾,🐉,🐲,🌵,🎄,🌲,🌳,🌴,🌱,🌿,☘️,🍀,🎍,🎋,🍃,🍂,🍁,🍄,🌾,💐,🌷,🌹,🥀,🌻,🌼,🌸,🌺,🌎,🌍,🌏,🌕,🌖,🌗,🌘,🌑,🌒,🌓,🌔,🌚,🌝,🌞,🌛,🌜,🌙,💫,⭐️,🌟,✨,⚡️,🔥,💥,☄️,☀️,🌤,⛅️,🌥,🌦,🌈,☁️,🌧,⛈,🌩,🌨,☃️,⛄️,❄️,🌬,💨,🌪,🌫,🌊,💧,💦,☔️"
|
17
|
-
}
|
18
|
-
},
|
19
|
-
{
|
20
|
-
"CVDataTitle" : "EmojiCategory-Foods",
|
21
|
-
"CVCategoryImage" : "Emoji-FoodsImage",
|
22
|
-
"CVCategoryData" : {
|
23
|
-
"CVSkipNullGlyphs" : false,
|
24
|
-
"Data" : "🍏,🍎,🍐,🍊,🍋,🍌,🍉,🍇,🍓,🍈,🍒,🍑,🍍,🥝,🥑,🍅,🍆,🥒,🥕,🌽,🌶,🥔,🍠,🌰,🥜,🍯,🥐,🍞,🥖,🧀,🥚,🍳,🥓,🥞,🍤,🍗,🍖,🍕,🌭,🍔,🍟,🥙,🌮,🌯,🥗,🥘,🍝,🍜,🍲,🍥,🍣,🍱,🍛,🍚,🍙,🍘,🍢,🍡,🍧,🍨,🍦,🍰,🎂,🍮,🍭,🍬,🍫,🍿,🍩,🍪,🥛,🍼,☕️,🍵,🍶,🍺,🍻,🥂,🍷,🥃,🍸,🍹,🍾,🥄,🍴,🍽"
|
25
|
-
}
|
26
|
-
},
|
27
|
-
{
|
28
|
-
"CVDataTitle" : "EmojiCategory-Activity",
|
29
|
-
"CVCategoryImage" : "Emoji-ActivityImage",
|
30
|
-
"CVCategoryData" : {
|
31
|
-
"CVSkipNullGlyphs" : false,
|
32
|
-
"Data" : "⚽️,🏀,🏈,⚾️,🎾,🏐,🏉,🎱,🏓,🏸,🥅,🏒,🏑,🏏,⛳️,🏹,🎣,🥊,🥋,⛸,🎿,⛷,🏂,🏋️♀️,🏋️,🤺,🤼♀️,🤼♂️,🤸♀️,🤸♂️,⛹️♀️,⛹️,🤾♀️,🤾♂️,🏌️♀️,🏌️,🏄♀️,🏄,🏊♀️,🏊,🤽♀️,🤽♂️,🚣♀️,🚣,🏇,🚴♀️,🚴,🚵♀️,🚵,🎽,🏅,🎖,🥇,🥈,🥉,🏆,🏵,🎗,🎫,🎟,🎪,🤹♀️,🤹♂️,🎭,🎨,🎬,🎤,🎧,🎼,🎹,🥁,🎷,🎺,🎸,🎻,🎲,🎯,🎳,🎮,🎰"
|
33
|
-
}
|
34
|
-
},
|
35
|
-
{
|
36
|
-
"CVDataTitle" : "EmojiCategory-Places",
|
37
|
-
"CVCategoryImage" : "Emoji-PlacesImage",
|
38
|
-
"CVCategoryData" : {
|
39
|
-
"CVSkipNullGlyphs" : false,
|
40
|
-
"Data" : "🚗,🚕,🚙,🚌,🚎,🏎,🚓,🚑,🚒,🚐,🚚,🚛,🚜,🛴,🚲,🛵,🏍,🚨,🚔,🚍,🚘,🚖,🚡,🚠,🚟,🚃,🚋,🚞,🚝,🚄,🚅,🚈,🚂,🚆,🚇,🚊,🚉,🚁,🛩,✈️,🛫,🛬,🚀,🛰,💺,🛶,⛵️,🛥,🚤,🛳,⛴,🚢,⚓️,🚧,⛽️,🚏,🚦,🚥,🗺,🗿,🗽,⛲️,🗼,🏰,🏯,🏟,🎡,🎢,🎠,⛱,🏖,🏝,⛰,🏔,🗻,🌋,🏜,🏕,⛺️,🛤,🛣,🏗,🏭,🏠,🏡,🏘,🏚,🏢,🏬,🏣,🏤,🏥,🏦,🏨,🏪,🏫,🏩,💒,🏛,⛪️,🕌,🕍,🕋,⛩,🗾,🎑,🏞,🌅,🌄,🌠,🎇,🎆,🌇,🌆,🏙,🌃,🌌,🌉,🌁"
|
41
|
-
}
|
42
|
-
},
|
43
|
-
{
|
44
|
-
"CVDataTitle" : "EmojiCategory-Objects",
|
45
|
-
"CVCategoryImage" : "Emoji-ObjectsImage",
|
46
|
-
"CVCategoryData" : {
|
47
|
-
"CVSkipNullGlyphs" : false,
|
48
|
-
"Data" : "⌚️,📱,📲,💻,⌨️,🖥,🖨,🖱,🖲,🕹,🗜,💽,💾,💿,📀,📼,📷,📸,📹,🎥,📽,🎞,📞,☎️,📟,📠,📺,📻,🎙,🎚,🎛,⏱,⏲,⏰,🕰,⌛️,⏳,📡,🔋,🔌,💡,🔦,🕯,🗑,🛢,💸,💵,💴,💶,💷,💰,💳,💎,⚖️,🔧,🔨,⚒,🛠,⛏,🔩,⚙️,⛓,🔫,💣,🔪,🗡,⚔️,🛡,🚬,⚰️,⚱️,🏺,🔮,📿,💈,⚗️,🔭,🔬,🕳,💊,💉,🌡,🚽,🚰,🚿,🛁,🛀,🛎,🔑,🗝,🚪,🛋,🛏,🛌,🖼,🛍,🛒,🎁,🎈,🎏,🎀,🎊,🎉,🎎,🏮,🎐,✉️,📩,📨,📧,💌,📥,📤,📦,🏷,📪,📫,📬,📭,📮,📯,📜,📃,📄,📑,📊,📈,📉,🗒,🗓,📆,📅,📇,🗃,🗳,🗄,📋,📁,📂,🗂,🗞,📰,📓,📔,📒,📕,📗,📘,📙,📚,📖,🔖,🔗,📎,🖇,📐,📏,📌,📍,✂️,🖊,🖋,✒️,🖌,🖍,📝,✏️,🔍,🔎,🔏,🔐,🔒,🔓"
|
49
|
-
}
|
50
|
-
},
|
51
|
-
{
|
52
|
-
"CVDataTitle" : "EmojiCategory-Symbols",
|
53
|
-
"CVCategoryImage" : "Emoji-SymbolImage",
|
54
|
-
"CVCategoryData" : {
|
55
|
-
"CVSkipNullGlyphs" : false,
|
56
|
-
"Data" : "❤️,💛,💚,💙,💜,🖤,💔,❣️,💕,💞,💓,💗,💖,💘,💝,💟,☮️,✝️,☪️,🕉,☸️,✡️,🔯,🕎,☯️,☦️,🛐,⛎,♈️,♉️,♊️,♋️,♌️,♍️,♎️,♏️,♐️,♑️,♒️,♓️,🆔,⚛️,🉑,☢️,☣️,📴,📳,🈶,🈚️,🈸,🈺,🈷️,✴️,🆚,💮,🉐,㊙️,㊗️,🈴,🈵,🈹,🈲,🅰️,🅱️,🆎,🆑,🅾️,🆘,❌,⭕️,🛑,⛔️,📛,🚫,💯,💢,♨️,🚷,🚯,🚳,🚱,🔞,📵,🚭,❗️,❕,❓,❔,‼️,⁉️,🔅,🔆,〽️,⚠️,🚸,🔱,⚜️,🔰,♻️,✅,🈯️,💹,❇️,✳️,❎,🌐,💠,Ⓜ️,🌀,💤,🏧,🚾,♿️,🅿️,🈳,🈂️,🛂,🛃,🛄,🛅,🚹,🚺,🚼,🚻,🚮,🎦,📶,🈁,🔣,ℹ️,🔤,🔡,🔠,🆖,🆗,🆙,🆒,🆕,🆓,0️⃣,1️⃣,2️⃣,3️⃣,4️⃣,5️⃣,6️⃣,7️⃣,8️⃣,9️⃣,🔟,🔢,#️⃣,*️⃣,▶️,⏸,⏯,⏹,⏺,⏭,⏮,⏩,⏪,⏫,⏬,◀️,🔼,🔽,➡️,⬅️,⬆️,⬇️,↗️,↘️,↙️,↖️,↕️,↔️,↪️,↩️,⤴️,⤵️,🔀,🔁,🔂,🔄,🔃,🎵,🎶,➕,➖,➗,✖️,💲,💱,™️,©️,®️,〰️,➰,➿,🔚,🔙,🔛,🔝,🔜,✔️,☑️,🔘,⚪️,⚫️,🔴,🔵,🔺,🔻,🔸,🔹,🔶,🔷,🔳,🔲,▪️,▫️,◾️,◽️,◼️,◻️,⬛️,⬜️,🔈,🔇,🔉,🔊,🔔,🔕,📣,📢,👁🗨,💬,💭,🗯,♠️,♣️,♥️,♦️,🃏,🎴,🀄️,🕐,🕑,🕒,🕓,🕔,🕕,🕖,🕗,🕘,🕙,🕚,🕛,🕜,🕝,🕞,🕟,🕠,🕡,🕢,🕣,🕤,🕥,🕦,🕧"
|
57
|
-
}
|
58
|
-
},
|
59
|
-
{
|
60
|
-
"CVDataTitle" : "EmojiCategory-Flags",
|
61
|
-
"CVCategoryImage" : "Emoji-FlagsImage",
|
62
|
-
"CVCategoryData" : {
|
63
|
-
"CVSkipNullGlyphs" : false,
|
64
|
-
"Data" : "🏳️,🏴,🏁,🚩,🏳️🌈,🇦🇫,🇦🇽,🇦🇱,🇩🇿,🇦🇸,🇦🇩,🇦🇴,🇦🇮,🇦🇶,🇦🇬,🇦🇷,🇦🇲,🇦🇼,🇦🇺,🇦🇹,🇦🇿,🇧🇸,🇧🇭,🇧🇩,🇧🇧,🇧🇾,🇧🇪,🇧🇿,🇧🇯,🇧🇲,🇧🇹,🇧🇴,🇧🇶,🇧🇦,🇧🇼,🇧🇷,🇮🇴,🇻🇬,🇧🇳,🇧🇬,🇧🇫,🇧🇮,🇨🇻,🇰🇭,🇨🇲,🇨🇦,🇮🇨,🇰🇾,🇨🇫,🇹🇩,🇨🇱,🇨🇳,🇨🇽,🇨🇨,🇨🇴,🇰🇲,🇨🇬,🇨🇩,🇨🇰,🇨🇷,🇨🇮,🇭🇷,🇨🇺,🇨🇼,🇨🇾,🇨🇿,🇩🇰,🇩🇯,🇩🇲,🇩🇴,🇪🇨,🇪🇬,🇸🇻,🇬🇶,🇪🇷,🇪🇪,🇪🇹,🇪🇺,🇫🇰,🇫🇴,🇫🇯,🇫🇮,🇫🇷,🇬🇫,🇵🇫,🇹🇫,🇬🇦,🇬🇲,🇬🇪,🇩🇪,🇬🇭,🇬🇮,🇬🇷,🇬🇱,🇬🇩,🇬🇵,🇬🇺,🇬🇹,🇬🇬,🇬🇳,🇬🇼,🇬🇾,🇭🇹,🇭🇳,🇭🇰,🇭🇺,🇮🇸,🇮🇳,🇮🇩,🇮🇷,🇮🇶,🇮🇪,🇮🇲,🇮🇱,🇮🇹,🇯🇲,🇯🇵,🎌,🇯🇪,🇯🇴,🇰🇿,🇰🇪,🇰🇮,🇽🇰,🇰🇼,🇰🇬,🇱🇦,🇱🇻,🇱🇧,🇱🇸,🇱🇷,🇱🇾,🇱🇮,🇱🇹,🇱🇺,🇲🇴,🇲🇰,🇲🇬,🇲🇼,🇲🇾,🇲🇻,🇲🇱,🇲🇹,🇲🇭,🇲🇶,🇲🇷,🇲🇺,🇾🇹,🇲🇽,🇫🇲,🇲🇩,🇲🇨,🇲🇳,🇲🇪,🇲🇸,🇲🇦,🇲🇿,🇲🇲,🇳🇦,🇳🇷,🇳🇵,🇳🇱,🇳🇨,🇳🇿,🇳🇮,🇳🇪,🇳🇬,🇳🇺,🇳🇫,🇲🇵,🇰🇵,🇳🇴,🇴🇲,🇵🇰,🇵🇼,🇵🇸,🇵🇦,🇵🇬,🇵🇾,🇵🇪,🇵🇭,🇵🇳,🇵🇱,🇵🇹,🇵🇷,🇶🇦,🇷🇪,🇷🇴,🇷🇺,🇷🇼,🇧🇱,🇸🇭,🇰🇳,🇱🇨,🇵🇲,🇻🇨,🇼🇸,🇸🇲,🇸🇹,🇸🇦,🇸🇳,🇷🇸,🇸🇨,🇸🇱,🇸🇬,🇸🇽,🇸🇰,🇸🇮,🇸🇧,🇸🇴,🇿🇦,🇬🇸,🇰🇷,🇸🇸,🇪🇸,🇱🇰,🇸🇩,🇸🇷,🇸🇿,🇸🇪,🇨🇭,🇸🇾,🇹🇼,🇹🇯,🇹🇿,🇹🇭,🇹🇱,🇹🇬,🇹🇰,🇹🇴,🇹🇹,🇹🇳,🇹🇷,🇹🇲,🇹🇨,🇹🇻,🇺🇬,🇺🇦,🇦🇪,🇬🇧,🇺🇸,🇻🇮,🇺🇾,🇺🇿,🇻🇺,🇻🇦,🇻🇪,🇻🇳,🇼🇫,🇪🇭,🇾🇪,🇿🇲,🇿🇼"
|
65
|
-
}
|
66
|
-
}
|
67
|
-
],
|
68
|
-
"CVViewFontList" : [
|
69
|
-
"AppleColorEmoji"
|
70
|
-
]
|
71
|
-
}
|
data/images/basecamp.png
DELETED
Binary file
|
data/images/basecampy.png
DELETED
Binary file
|
data/images/bowtie.png
DELETED
Binary file
|
data/images/feelsgood.png
DELETED
Binary file
|
data/images/finnadie.png
DELETED
Binary file
|
data/images/goberserk.png
DELETED
Binary file
|
data/images/godmode.png
DELETED
Binary file
|
data/images/hurtrealbad.png
DELETED
Binary file
|
data/images/neckbeard.png
DELETED
Binary file
|
data/images/octocat.png
DELETED
Binary file
|
data/images/rage1.png
DELETED
Binary file
|
data/images/rage2.png
DELETED
Binary file
|
data/images/rage3.png
DELETED
Binary file
|
data/images/rage4.png
DELETED
Binary file
|
data/images/shipit.png
DELETED
Binary file
|
data/images/suspect.png
DELETED
Binary file
|
data/images/trollface.png
DELETED
Binary file
|
data/lib/emoji/cli.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
require 'emoji/extractor'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'optparse'
|
4
|
-
|
5
|
-
module Emoji
|
6
|
-
module CLI
|
7
|
-
extend self
|
8
|
-
|
9
|
-
InvalidUsage = Class.new(RuntimeError)
|
10
|
-
|
11
|
-
def dispatch(argv)
|
12
|
-
cmd = argv[0]
|
13
|
-
argv = argv[1..-1]
|
14
|
-
|
15
|
-
case cmd
|
16
|
-
when "extract"
|
17
|
-
public_send(cmd, argv)
|
18
|
-
when "help", "--help", "-h"
|
19
|
-
help
|
20
|
-
else
|
21
|
-
raise InvalidUsage
|
22
|
-
end
|
23
|
-
|
24
|
-
return 0
|
25
|
-
rescue InvalidUsage, OptionParser::InvalidArgument, OptionParser::InvalidOption => err
|
26
|
-
unless err.message == err.class.to_s
|
27
|
-
$stderr.puts err.message
|
28
|
-
$stderr.puts
|
29
|
-
end
|
30
|
-
$stderr.puts usage_text
|
31
|
-
return 1
|
32
|
-
end
|
33
|
-
|
34
|
-
def help
|
35
|
-
puts usage_text
|
36
|
-
end
|
37
|
-
|
38
|
-
VALID_SIZES = [ 20, 32, 40, 48, 64, 96, 160 ]
|
39
|
-
|
40
|
-
def extract(argv)
|
41
|
-
size = 64
|
42
|
-
|
43
|
-
OptionParser.new do |opts|
|
44
|
-
opts.on("--size=#{size}", Integer) do |val|
|
45
|
-
if VALID_SIZES.include?(val)
|
46
|
-
size = val
|
47
|
-
else
|
48
|
-
raise InvalidUsage, "size should be one of: #{VALID_SIZES.join(', ')}"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end.parse!(argv)
|
52
|
-
|
53
|
-
raise InvalidUsage unless argv.size == 1
|
54
|
-
path = argv[0]
|
55
|
-
|
56
|
-
Emoji::Extractor.new(size, path).extract!
|
57
|
-
Dir["#{Emoji.images_path}/*.png"].each do |png|
|
58
|
-
FileUtils.cp(png, File.join(path, File.basename(png)))
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def usage_text
|
63
|
-
<<EOF
|
64
|
-
Usage: gemoji extract <path> [--size=64]
|
65
|
-
EOF
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
data/lib/emoji/extractor.rb
DELETED
@@ -1,190 +0,0 @@
|
|
1
|
-
require 'emoji'
|
2
|
-
require 'fileutils'
|
3
|
-
|
4
|
-
module Emoji
|
5
|
-
class Extractor
|
6
|
-
EMOJI_TTF = "/System/Library/Fonts/Apple Color Emoji.ttc"
|
7
|
-
|
8
|
-
attr_reader :size, :images_path
|
9
|
-
|
10
|
-
def initialize(size, images_path)
|
11
|
-
@size = size
|
12
|
-
@images_path = images_path
|
13
|
-
end
|
14
|
-
|
15
|
-
def each(&block)
|
16
|
-
return to_enum(__method__) unless block_given?
|
17
|
-
|
18
|
-
File.open(EMOJI_TTF, 'rb') do |file|
|
19
|
-
font_offsets = parse_ttc(file)
|
20
|
-
file.pos = font_offsets[0]
|
21
|
-
|
22
|
-
tables = parse_tables(file)
|
23
|
-
glyph_index = extract_glyph_index(file, tables)
|
24
|
-
|
25
|
-
each_glyph_bitmap(file, tables, glyph_index, &block)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def extract!
|
30
|
-
each do |glyph_name, type, binread|
|
31
|
-
if emoji = glyph_name_to_emoji(glyph_name)
|
32
|
-
image_filename = "#{images_path}/#{emoji.image_filename}"
|
33
|
-
FileUtils.mkdir_p(File.dirname(image_filename))
|
34
|
-
File.open(image_filename, 'wb') { |f| f.write binread.call }
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
GENDER_MAP = {
|
42
|
-
"M" => "\u{2642}",
|
43
|
-
"W" => "\u{2640}",
|
44
|
-
}
|
45
|
-
|
46
|
-
FAMILY_MAP = {
|
47
|
-
"B" => "\u{1f466}",
|
48
|
-
"G" => "\u{1f467}",
|
49
|
-
"M" => "\u{1f468}",
|
50
|
-
"W" => "\u{1f469}",
|
51
|
-
}.freeze
|
52
|
-
|
53
|
-
FAMILY = "1F46A"
|
54
|
-
COUPLE = "1F491"
|
55
|
-
KISS = "1F48F"
|
56
|
-
|
57
|
-
def glyph_name_to_emoji(glyph_name)
|
58
|
-
return if glyph_name =~ /\.[1-5]($|\.)/
|
59
|
-
zwj = Emoji::ZERO_WIDTH_JOINER
|
60
|
-
v16 = Emoji::VARIATION_SELECTOR_16
|
61
|
-
|
62
|
-
if glyph_name =~ /^u(#{FAMILY}|#{COUPLE}|#{KISS})\.([#{FAMILY_MAP.keys.join('')}]+)$/
|
63
|
-
if $1 == FAMILY ? $2 == "MWB" : $2 == "WM"
|
64
|
-
raw = [$1.hex].pack('U')
|
65
|
-
else
|
66
|
-
if $1 == COUPLE
|
67
|
-
middle = "#{zwj}\u{2764}#{v16}#{zwj}" # heavy black heart
|
68
|
-
elsif $1 == KISS
|
69
|
-
middle = "#{zwj}\u{2764}#{v16}#{zwj}\u{1F48B}#{zwj}" # heart + kiss mark
|
70
|
-
else
|
71
|
-
middle = zwj
|
72
|
-
end
|
73
|
-
raw = $2.split('').map { |c| FAMILY_MAP.fetch(c) }.join(middle)
|
74
|
-
end
|
75
|
-
candidates = [raw]
|
76
|
-
else
|
77
|
-
raw = glyph_name.gsub(/(^|_)u([0-9A-F]+)/) { ($1.empty?? $1 : zwj) + [$2.hex].pack('U') }
|
78
|
-
raw.sub!(/\.0\b/, '')
|
79
|
-
raw.sub!(/\.(#{GENDER_MAP.keys.join('|')})$/) { v16 + zwj + GENDER_MAP.fetch($1) }
|
80
|
-
candidates = [raw]
|
81
|
-
candidates << raw.sub(v16, '') if raw.include?(v16)
|
82
|
-
candidates << raw.gsub(zwj, '') if raw.include?(zwj)
|
83
|
-
candidates.dup.each { |c| candidates << (c + v16) }
|
84
|
-
end
|
85
|
-
|
86
|
-
candidates.map { |c| Emoji.find_by_unicode(c) }.compact.first
|
87
|
-
end
|
88
|
-
|
89
|
-
# https://www.microsoft.com/typography/otspec/otff.htm
|
90
|
-
def parse_ttc(io)
|
91
|
-
header_name = io.read(4).unpack('a*')[0]
|
92
|
-
raise unless "ttcf" == header_name
|
93
|
-
header_version, num_fonts = io.read(4*2).unpack('l>N')
|
94
|
-
# parse_version(header_version) #=> 2.0
|
95
|
-
io.read(4 * num_fonts).unpack('N*')
|
96
|
-
end
|
97
|
-
|
98
|
-
def parse_tables(io)
|
99
|
-
sfnt_version, num_tables = io.read(4 + 2*4).unpack('Nn')
|
100
|
-
# sfnt_version #=> 0x00010000
|
101
|
-
num_tables.times.each_with_object({}) do |_, tables|
|
102
|
-
tag, checksum, offset, length = io.read(4 + 4*3).unpack('a4N*')
|
103
|
-
tables[tag] = {
|
104
|
-
checksum: checksum,
|
105
|
-
offset: offset,
|
106
|
-
length: length,
|
107
|
-
}
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
GlyphIndex = Struct.new(:length, :name_index, :names) do
|
112
|
-
def name_for(glyph_id)
|
113
|
-
index = name_index[glyph_id]
|
114
|
-
names[index - 257]
|
115
|
-
end
|
116
|
-
|
117
|
-
def each(&block)
|
118
|
-
length.times(&block)
|
119
|
-
end
|
120
|
-
|
121
|
-
def each_with_name
|
122
|
-
each do |glyph_id|
|
123
|
-
yield glyph_id, name_for(glyph_id)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def extract_glyph_index(io, tables)
|
129
|
-
postscript_table = tables.fetch('post')
|
130
|
-
io.pos = postscript_table[:offset]
|
131
|
-
end_pos = io.pos + postscript_table[:length]
|
132
|
-
|
133
|
-
parse_version(io.read(32).unpack('l>')[0]) #=> 2.0
|
134
|
-
num_glyphs = io.read(2).unpack('n')[0]
|
135
|
-
glyph_name_index = io.read(2*num_glyphs).unpack('n*')
|
136
|
-
|
137
|
-
glyph_names = []
|
138
|
-
while io.pos < end_pos
|
139
|
-
length = io.read(1).unpack('C')[0]
|
140
|
-
glyph_names << io.read(length)
|
141
|
-
end
|
142
|
-
|
143
|
-
GlyphIndex.new(num_glyphs, glyph_name_index, glyph_names)
|
144
|
-
end
|
145
|
-
|
146
|
-
# https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6sbix.html
|
147
|
-
def each_glyph_bitmap(io, tables, glyph_index)
|
148
|
-
io.pos = sbix_offset = tables.fetch('sbix')[:offset]
|
149
|
-
strike = extract_sbix_strike(io, glyph_index.length, size)
|
150
|
-
|
151
|
-
glyph_index.each_with_name do |glyph_id, glyph_name|
|
152
|
-
glyph_offset = strike[:glyph_data_offset][glyph_id]
|
153
|
-
next_glyph_offset = strike[:glyph_data_offset][glyph_id + 1]
|
154
|
-
|
155
|
-
if glyph_offset && next_glyph_offset && glyph_offset < next_glyph_offset
|
156
|
-
io.pos = sbix_offset + strike[:offset] + glyph_offset
|
157
|
-
x, y, type = io.read(2*2 + 4).unpack('s2A4')
|
158
|
-
yield glyph_name, type, -> { io.read(next_glyph_offset - glyph_offset - 8) }
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
def extract_sbix_strike(io, num_glyphs, image_size)
|
164
|
-
sbix_offset = io.pos
|
165
|
-
version, flags, num_strikes = io.read(2*2 + 4).unpack('n2N')
|
166
|
-
strike_offsets = num_strikes.times.map { io.read(4).unpack('N')[0] }
|
167
|
-
|
168
|
-
strike_offsets.each do |strike_offset|
|
169
|
-
io.pos = sbix_offset + strike_offset
|
170
|
-
ppem, resolution = io.read(4*2).unpack('n2')
|
171
|
-
next unless ppem == size
|
172
|
-
|
173
|
-
data_offsets = io.read(4 * (num_glyphs+1)).unpack('N*')
|
174
|
-
return {
|
175
|
-
ppem: ppem,
|
176
|
-
resolution: resolution,
|
177
|
-
offset: strike_offset,
|
178
|
-
glyph_data_offset: data_offsets,
|
179
|
-
}
|
180
|
-
end
|
181
|
-
return nil
|
182
|
-
end
|
183
|
-
|
184
|
-
def parse_version(num)
|
185
|
-
major = num >> 16
|
186
|
-
minor = num & 0xFFFF
|
187
|
-
"#{major}.#{minor}"
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|