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.
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
- # Chars from Apple's palette which must have VARIATION_SELECTOR_16 to render:
81
- TEXT_GLYPHS = ["🈷", "🈂", "🅰", "🅱", "🅾", "©", "®", "™", "〰"].freeze
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') { |file| JSON.parse(file.read) }
85
- data.each do |raw_emoji|
86
- self.create(nil) do |emoji|
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
- emoji.category = raw_emoji['category']
95
- emoji.description = raw_emoji['description']
96
- emoji.unicode_version = raw_emoji['unicode_version']
97
- emoji.ios_version = raw_emoji['ios_version']
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
- raw = raw_emoji['emoji']
104
- next unless raw
105
- no_gender = raw.sub(/(#{VARIATION_SELECTOR_16})?#{ZERO_WIDTH_JOINER}(#{FEMALE_SYMBOL}|#{MALE_SYMBOL})/, '')
106
- next unless $2
107
- emoji = find_by_unicode(no_gender)
108
- next unless emoji
109
- edit_emoji(emoji) do
110
- emoji.add_unicode_alias(
111
- $2 == FEMALE_SYMBOL ?
112
- raw.sub(FEMALE_SYMBOL, MALE_SYMBOL) :
113
- raw.sub(MALE_SYMBOL, FEMALE_SYMBOL)
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Emoji
2
4
  class Character
3
5
  # Inspect individual Unicode characters in a string by dumping its
data/lib/gemoji.rb CHANGED
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'emoji'
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: 3.0.1
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: 2019-04-25 00:00:00.000000000 Z
11
+ date: 2021-07-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Character information and metadata for standard and custom emoji.
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: '0'
42
+ version: 1.3.1
64
43
  requirements: []
65
- rubyforge_project:
66
- rubygems_version: 2.5.2.3
67
- signing_key:
44
+ rubygems_version: 3.0.3
45
+ signing_key:
68
46
  specification_version: 4
69
- summary: Emoji library
47
+ summary: Unicode emoji library
70
48
  test_files: []
data/bin/gemoji DELETED
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'emoji/cli'
3
-
4
- exit_code = Emoji::CLI.dispatch(ARGV)
5
- exit exit_code
@@ -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
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
@@ -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